├── .gcloudignore ├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── NOTICE ├── README.md ├── SECURITY.md ├── TODO.md ├── Version ├── cloudfunctions.go ├── cmd ├── README.md ├── cli.go ├── command │ ├── bundle.go │ ├── cache.go │ ├── extension.go │ ├── generate.go │ ├── mcp.go │ ├── plugin.go │ ├── router.go │ ├── run.go │ ├── service.go │ ├── tmpl │ │ ├── README.md │ │ ├── ext │ │ │ ├── go.modx │ │ │ └── init.gox │ │ └── pkg │ │ │ ├── bootstrap │ │ │ └── bootstrap.gox │ │ │ ├── checksum │ │ │ └── init.gox │ │ │ ├── dependency │ │ │ └── init.gox │ │ │ ├── init.gox │ │ │ └── plugin │ │ │ └── init.gox │ ├── touch.go │ └── translate.go ├── datly │ ├── build.yaml │ └── datly.go ├── env │ ├── cloud.go │ ├── debug.go │ ├── imports.go │ └── metadata.go ├── option.go ├── options │ ├── args.go │ ├── auth.go │ ├── build.go │ ├── bundle.go │ ├── cache.go │ ├── conn.go │ ├── embedding.go │ ├── embedding_test.go │ ├── ext.go │ ├── ext │ │ └── init │ │ │ └── README.md │ ├── gen.go │ ├── init.go │ ├── mbus.go │ ├── mcp.go │ ├── options.go │ ├── path.go │ ├── plugin.go │ ├── query.go │ ├── repository.go │ ├── router.go │ ├── rule.go │ ├── run.go │ ├── shared.go │ ├── touch.go │ └── translate.go └── resource │ └── mysql.json ├── doc ├── README.md ├── asset │ ├── datly_arch.drawio.png │ ├── datly_executor.drawio.png │ ├── datly_reader.drawio.png │ └── raw_credentials.json ├── example_test.go ├── extension │ ├── EXAMPLES.md │ └── README.md └── security │ └── README.md ├── e2e ├── README.md ├── cloud │ └── jwt │ │ ├── private.enc │ │ └── public.enc ├── debug │ └── datly.go ├── debug_gen │ └── datly.go ├── local │ ├── build.yaml │ ├── datastore │ │ ├── datastore.yaml │ │ ├── dyndb │ │ │ ├── populate │ │ │ │ └── USER_ACL.json │ │ │ └── schema.ddl │ │ └── mysql │ │ │ ├── populate │ │ │ ├── BAR.json │ │ │ ├── CITY.json │ │ │ ├── DATLY_JOBS.json │ │ │ ├── DISTRICT.json │ │ │ ├── EVENTS.json │ │ │ ├── EVENTS_PERFORMANCE.json │ │ │ ├── FOOS.json │ │ │ ├── FOOS_PERFORMANCE.json │ │ │ ├── OBJECTS.json │ │ │ ├── PRODUCT.json │ │ │ ├── PRODUCT_JN.json │ │ │ ├── TEAM.json │ │ │ ├── USER.json │ │ │ ├── USER_METADATA.json │ │ │ ├── USER_TEAM.json │ │ │ └── VENDOR.json │ │ │ └── schema.ddl │ ├── jwt │ │ ├── hmac.enc │ │ ├── private.enc │ │ └── public.enc │ ├── regression │ │ ├── app.yaml │ │ ├── cases │ │ │ ├── 001_one_to_many │ │ │ │ ├── expect.json │ │ │ │ ├── expect_2.txt │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendor_list.dql │ │ │ ├── 002_uri_param │ │ │ │ ├── doc.yaml │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ ├── vendor_details.sql │ │ │ │ └── vendor_details_vendor.sql │ │ │ ├── 003_oauth │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendor_auth.sql │ │ │ ├── 004_update │ │ │ │ ├── expect.json │ │ │ │ ├── expect │ │ │ │ │ └── PRODUCT.json │ │ │ │ ├── gen.json │ │ │ │ ├── product_update.sql │ │ │ │ └── test.yaml │ │ │ ├── 005_sumary │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendor_meta.sql │ │ │ ├── 006_tree │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── user_tree.sql │ │ │ ├── 007_child_meta │ │ │ │ ├── child_meta.sql │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ └── test.yaml │ │ │ ├── 008_record_pagination │ │ │ │ ├── district_pagination.sql │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ └── test.yaml │ │ │ ├── 009_apikey │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendor_apikey.sql │ │ │ ├── 010_codecs │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendors_codec.sql │ │ │ ├── 011_env │ │ │ │ ├── environment.sql │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ └── test.yaml │ │ │ ├── 012_meta_format │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── meta_format.sql │ │ │ │ └── test.yaml │ │ │ ├── 013_col_in │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendor_col_in.sql │ │ │ ├── 014_header_params │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── header_vendors.sql │ │ │ │ └── test.yaml │ │ │ ├── 015_index_by │ │ │ │ ├── expect │ │ │ │ │ └── TEAM.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── user_team.sql │ │ │ ├── 016_team_delete │ │ │ │ ├── gen.json │ │ │ │ ├── team.sql │ │ │ │ └── test.yaml │ │ │ ├── 017_generate_post_basic_one │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ ├── post_basic_one.sql │ │ │ │ └── test.yaml │ │ │ ├── 018_generate_post_basic_many │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── expect_t2.json │ │ │ │ ├── gen.json │ │ │ │ ├── post_basic_many.sql │ │ │ │ └── test.yaml │ │ │ ├── 019_generate_post_comprehensive_many │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── expect_t2.json │ │ │ │ ├── gen.json │ │ │ │ ├── post_comprehensive_many.sql │ │ │ │ └── test.yaml │ │ │ ├── 020_generate_post_except │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ ├── post_except.sql │ │ │ │ └── test.yaml │ │ │ ├── 021_generate_post_explicit_columns │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ ├── post_explicit.sql │ │ │ │ └── test.yaml │ │ │ ├── 022_generate_post_one_one │ │ │ │ ├── expect_t0.json │ │ │ │ ├── gen.json │ │ │ │ ├── post_one_one.sql │ │ │ │ └── test.yaml │ │ │ ├── 023_generate_post_one_many │ │ │ │ ├── expect_t0.json │ │ │ │ ├── gen.json │ │ │ │ ├── post_one_many.sql │ │ │ │ └── test.yaml │ │ │ ├── 024_validator_codec │ │ │ │ ├── Events.go │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── validator_codec.sql │ │ │ ├── 025_structql_velocity │ │ │ │ ├── Events.go │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ ├── structql_velty.sql │ │ │ │ └── test.yaml │ │ │ ├── 026_transform_service │ │ │ │ ├── Events.go │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── transform_service.sql │ │ │ ├── 027_generate_put_basic_one │ │ │ │ ├── expect │ │ │ │ │ └── FOOS.json │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ ├── put_basic_one.sql │ │ │ │ └── test.yaml │ │ │ ├── 028_generate_put_basic_many │ │ │ │ ├── expect │ │ │ │ │ └── FOOS.json │ │ │ │ ├── expect_t0.json │ │ │ │ ├── gen.json │ │ │ │ ├── put_basic_many.sql │ │ │ │ └── test.yaml │ │ │ ├── 029_generate_put_one_many │ │ │ │ ├── expect │ │ │ │ │ ├── FOOS.json │ │ │ │ │ └── FOOS_PERFORMANCE.json │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ ├── put_one_many.sql │ │ │ │ └── test.yaml │ │ │ ├── 030_insert_acl │ │ │ │ ├── Events.go │ │ │ │ ├── gen.json │ │ │ │ ├── skip.txt │ │ │ │ ├── test.yaml │ │ │ │ └── user_acl.sql │ │ │ ├── 031_generate_patch_basic_one │ │ │ │ ├── expect │ │ │ │ │ └── FOOS.json │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ ├── patch_basic_one.sql │ │ │ │ └── test.yaml │ │ │ ├── 032_generate_patch_basic_many │ │ │ │ ├── expect │ │ │ │ │ └── FOOS.json │ │ │ │ ├── expect_t0.json │ │ │ │ ├── gen.json │ │ │ │ ├── patch_basic_many.sql │ │ │ │ └── test.yaml │ │ │ ├── 033_generate_patch_many_many │ │ │ │ ├── expect │ │ │ │ │ └── FOOS.json │ │ │ │ ├── expect_t0.json │ │ │ │ ├── gen.json │ │ │ │ ├── patch_basic_many_many.sql │ │ │ │ └── test.yaml │ │ │ ├── 034_inserter │ │ │ │ ├── expect_t0.json │ │ │ │ ├── gen.json │ │ │ │ ├── inserter.sql │ │ │ │ └── test.yaml │ │ │ ├── 035_updater │ │ │ │ ├── expect_t0.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── updater.sql │ │ │ ├── 036_differ │ │ │ │ ├── differ.sql │ │ │ │ ├── foos.go │ │ │ │ ├── gen.json │ │ │ │ ├── pre_differ.sql │ │ │ │ └── test.yaml │ │ │ ├── 037_plugins │ │ │ │ ├── foo.go │ │ │ │ ├── gen.json │ │ │ │ ├── plugins.sql │ │ │ │ └── test.yaml │ │ │ ├── 038_mysql_boolean │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── user_metadata.sql │ │ │ ├── 039_generate_post_comprehensive_one │ │ │ │ ├── expect_t0.json │ │ │ │ ├── gen.json │ │ │ │ ├── post_comprehensive_one.sql │ │ │ │ └── test.yaml │ │ │ ├── 040_parameters_order │ │ │ │ ├── data.go │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ ├── parameters_order.sql │ │ │ │ └── test.yaml │ │ │ ├── 041_custom_response │ │ │ │ ├── custom_response.sql │ │ │ │ ├── data.go │ │ │ │ ├── expect_t0.json │ │ │ │ ├── expect_t1.json │ │ │ │ ├── gen.json │ │ │ │ └── test.yaml │ │ │ ├── 042_json_codec │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── json_codec.sql │ │ │ │ ├── test.yaml │ │ │ │ └── types.go │ │ │ ├── 043_json_codec_single │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── json_codec_single.sql │ │ │ │ ├── test.yaml │ │ │ │ └── types.go │ │ │ ├── 044_inline_json_codec │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── inlinejson_codec.sql │ │ │ │ ├── test.yaml │ │ │ │ └── types.go │ │ │ ├── 045_raw_json │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── raw_json.sql │ │ │ │ ├── test.yaml │ │ │ │ └── types.go │ │ │ ├── 046_raw_json_expr │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── raw_json_tag.sql │ │ │ │ └── test.yaml │ │ │ ├── 047_raw_json_tag │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── raw_json_expr.sql │ │ │ │ └── test.yaml │ │ │ ├── 048_json_persist_with_type │ │ │ │ ├── custom_unmarshall_velty.sql │ │ │ │ ├── expect.json │ │ │ │ ├── expect2.json │ │ │ │ ├── gen.json │ │ │ │ ├── preference.go │ │ │ │ └── test.yaml │ │ │ ├── 049_oauth_hmac │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendor_hauth.sql │ │ │ ├── 050_redirect │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── redirect.sql │ │ │ │ └── test.yaml │ │ │ ├── 051_redirect_vendors │ │ │ │ ├── expect.json │ │ │ │ ├── expect2.json │ │ │ │ ├── gen.json │ │ │ │ ├── redirect_vendor_details.sql │ │ │ │ ├── redirect_vendor_list.sql │ │ │ │ ├── router.vm │ │ │ │ ├── skip.txt │ │ │ │ └── test.yaml │ │ │ ├── 052_json_persist │ │ │ │ ├── expect.json │ │ │ │ ├── expect2.json │ │ │ │ ├── gen.json │ │ │ │ ├── json_persist.sql │ │ │ │ ├── preference.go │ │ │ │ └── test.yaml │ │ │ ├── 053_dql_persist │ │ │ │ ├── dql_persist.dql │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── preference.go │ │ │ │ └── test.yaml │ │ │ ├── 054_persist_inlined_json │ │ │ │ ├── dql_persist_inlined.dql │ │ │ │ ├── expect.json │ │ │ │ ├── expect2.json │ │ │ │ ├── gen.json │ │ │ │ ├── preference.go │ │ │ │ └── test.yaml │ │ │ ├── 055_variables │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── properties.json │ │ │ │ ├── test.yaml │ │ │ │ └── vars.sql │ │ │ ├── 056_custom_patch │ │ │ │ ├── expect_t0.json │ │ │ │ ├── foos.go │ │ │ │ ├── gen.json │ │ │ │ ├── patch_custom.sql │ │ │ │ ├── pre_gen.json │ │ │ │ ├── pre_patch_custom.sql │ │ │ │ └── test.yaml │ │ │ ├── 057_patch_types │ │ │ │ ├── expect_t0.json │ │ │ │ ├── foos.go │ │ │ │ ├── gen.json │ │ │ │ ├── patch_types.sql │ │ │ │ ├── pre_gen.json │ │ │ │ ├── pre_patch_types.sql │ │ │ │ └── test.yaml │ │ │ ├── 058_tabjson_one_to_many │ │ │ │ ├── expect.json │ │ │ │ ├── expect_2.txt │ │ │ │ ├── gen.json │ │ │ │ ├── tabular_vendor_list.sql │ │ │ │ └── test.yaml │ │ │ ├── 059_tabjson_basic │ │ │ │ ├── bar_list.sql │ │ │ │ ├── expect.json │ │ │ │ ├── expect_2.txt │ │ │ │ ├── gen.json │ │ │ │ └── test.yaml │ │ │ ├── 060_tabjson_comprehensive │ │ │ │ ├── bar_comprehensive_list.sql │ │ │ │ ├── expect.json │ │ │ │ ├── expect_2.txt │ │ │ │ ├── gen.json │ │ │ │ └── test.yaml │ │ │ ├── 061_read_async │ │ │ │ ├── expect_1.json │ │ │ │ ├── expect_2.json │ │ │ │ ├── gen.json │ │ │ │ ├── root.go │ │ │ │ ├── test.yaml │ │ │ │ └── vendor_auth_async.sql │ │ │ ├── 062_predicates │ │ │ │ ├── expect.json │ │ │ │ ├── expect2.json │ │ │ │ ├── expect3.json │ │ │ │ ├── expect4.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendors_predicate.sql │ │ │ ├── 063_external_parameters │ │ │ │ ├── expect.json │ │ │ │ ├── expect2.json │ │ │ │ ├── expect3.json │ │ │ │ ├── expect4.json │ │ │ │ ├── external_parameters.sql │ │ │ │ ├── gen.json │ │ │ │ ├── parameters.sql │ │ │ │ └── test.yaml │ │ │ ├── 064_params_group │ │ │ │ ├── expect1.json │ │ │ │ ├── expect2.json │ │ │ │ ├── expect3.json │ │ │ │ ├── gen.json │ │ │ │ ├── params_group.sql │ │ │ │ ├── templates.yaml │ │ │ │ └── test.yaml │ │ │ ├── 065_encode_struct │ │ │ │ ├── encode_struct.sql │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendor.go │ │ │ ├── 066_xls_output │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendor_xls.sql │ │ │ ├── 067_xml_basic │ │ │ │ ├── expect.xml │ │ │ │ ├── expect_2.txt │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── xml_bar_list.sql │ │ │ ├── 068_xml_one_to_many │ │ │ │ ├── expect.xml │ │ │ │ ├── expect_2.txt │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── xml_tabular_vendor_list.sql │ │ │ └── 069_encode_struct_pkg │ │ │ │ ├── encode_struct_pkg.sql │ │ │ │ ├── expect.json │ │ │ │ ├── gen.json │ │ │ │ ├── test.yaml │ │ │ │ └── vendor.go │ │ ├── db.yaml │ │ ├── default │ │ │ └── expec.json │ │ ├── partial_config.json │ │ ├── regression.yaml │ │ └── rule.yaml │ ├── run.yaml │ ├── system.yaml │ └── validator │ │ └── src │ │ ├── go.mod │ │ └── main │ │ └── validator.go └── mcp │ └── debug.go ├── gateway ├── app │ └── datly.go ├── async.go ├── config.go ├── doc.go ├── example │ ├── README.md │ ├── dependencies │ │ └── acl.yaml │ ├── deploy.yaml │ ├── deploy_s3.yaml │ ├── routes │ │ └── test │ │ │ ├── dual.yaml │ │ │ └── performance.yaml │ └── script │ │ └── bigquery │ │ └── create.sql ├── mcp.go ├── option.go ├── route.go ├── route_component.go ├── route_config.go ├── route_metric.go ├── route_openapi.go ├── route_state.go ├── route_status.go ├── route_struct.go ├── route_warmup.go ├── router.go ├── router │ ├── README.md │ ├── handler.go │ ├── marshal │ │ ├── config │ │ │ └── default.go │ │ ├── context.go │ │ ├── init.go │ │ ├── json │ │ │ ├── cache.go │ │ │ ├── default.go │ │ │ ├── enc.go │ │ │ ├── error.go │ │ │ ├── field.go │ │ │ ├── filter.go │ │ │ ├── init.go │ │ │ ├── marshal.go │ │ │ ├── marshal_test.go │ │ │ ├── marshallable.go │ │ │ ├── marshaller.go │ │ │ ├── marshaller_array.go │ │ │ ├── marshaller_bool.go │ │ │ ├── marshaller_bool_ptr.go │ │ │ ├── marshaller_custom.go │ │ │ ├── marshaller_float.go │ │ │ ├── marshaller_float_ptr.go │ │ │ ├── marshaller_inlinable.go │ │ │ ├── marshaller_int.go │ │ │ ├── marshaller_int_ptr.go │ │ │ ├── marshaller_interface.go │ │ │ ├── marshaller_map.go │ │ │ ├── marshaller_ptr.go │ │ │ ├── marshaller_raw_message.go │ │ │ ├── marshaller_slice.go │ │ │ ├── marshaller_strings.go │ │ │ ├── marshaller_strings_ptr.go │ │ │ ├── marshaller_struct.go │ │ │ ├── marshaller_time.go │ │ │ ├── marshaller_time_ptr.go │ │ │ ├── marshaller_uint.go │ │ │ ├── marshaller_uint_ptr.go │ │ │ ├── option.go │ │ │ ├── presence.go │ │ │ ├── session.go │ │ │ └── tag.go │ │ ├── state.go │ │ ├── tabjson │ │ │ ├── accessor.go │ │ │ ├── buffer.go │ │ │ ├── buffer_test.go │ │ │ ├── config.go │ │ │ ├── index.go │ │ │ ├── object.go │ │ │ ├── reader.go │ │ │ ├── reader_test.go │ │ │ ├── session.go │ │ │ ├── tabjson.go │ │ │ ├── tabjson_test.go │ │ │ ├── tags.go │ │ │ ├── tree.go │ │ │ └── writer.go │ │ └── transforms.go │ ├── metrics.go │ ├── openapi │ │ ├── openapi3.go │ │ ├── openapi3 │ │ │ ├── callbacks.go │ │ │ ├── components.go │ │ │ ├── content.go │ │ │ ├── encoding.go │ │ │ ├── example.go │ │ │ ├── extension.go │ │ │ ├── externaldoc.go │ │ │ ├── header.go │ │ │ ├── info.go │ │ │ ├── json.go │ │ │ ├── link.go │ │ │ ├── media.go │ │ │ ├── oauth.go │ │ │ ├── openapi.go │ │ │ ├── operation.go │ │ │ ├── parameter.go │ │ │ ├── path.go │ │ │ ├── request.go │ │ │ ├── response.go │ │ │ ├── schemas.go │ │ │ ├── security.go │ │ │ ├── server.go │ │ │ ├── session.go │ │ │ └── tag.go │ │ ├── path.go │ │ ├── schema.go │ │ └── tag.go │ ├── proxy │ │ └── writer.go │ ├── resource.go │ ├── response.go │ ├── route.go │ ├── sanitize.go │ └── status │ │ └── error.go ├── runtime │ ├── apigw │ │ ├── adapter │ │ │ ├── request.go │ │ │ └── response.go │ │ ├── app │ │ │ └── datly.go │ │ ├── deploy.yaml │ │ ├── doc.go │ │ ├── handler.go │ │ ├── policy │ │ │ └── datly.json │ │ └── resource │ │ │ └── config.json │ ├── async │ │ ├── adapter │ │ │ ├── gs │ │ │ │ └── event.go │ │ │ └── s3 │ │ │ │ └── event.go │ │ └── lambda │ │ │ ├── app │ │ │ └── datly.go │ │ │ └── handler.go │ ├── docker │ │ ├── Dockerfile │ │ └── Version │ ├── gcf │ │ ├── README.md │ │ ├── deploy.yaml │ │ ├── doc.go │ │ ├── handler.go │ │ └── resource │ │ │ └── config.json │ ├── gcr │ │ ├── deploy.yaml │ │ └── doc.go │ ├── lambda │ │ ├── adapter │ │ │ ├── request.go │ │ │ └── response.go │ │ ├── app │ │ │ └── datly.go │ │ ├── deploy.yaml │ │ ├── doc.go │ │ ├── handler.go │ │ ├── policy │ │ │ └── datly.json │ │ ├── resource │ │ │ └── config.json │ │ └── response.go │ ├── meta │ │ ├── auth.go │ │ └── config.go │ ├── segment.go │ ├── segment_test.go │ ├── serverless │ │ └── service.go │ └── standalone │ │ ├── cli.go │ │ ├── config.go │ │ ├── deploy.yaml │ │ ├── endpoint │ │ └── config.go │ │ ├── handler │ │ └── status.go │ │ ├── option.go │ │ ├── resource │ │ └── config.json │ │ └── server.go ├── service.go ├── session.go ├── singleton.go └── warmup │ └── cache.go ├── go.mod ├── go.sum ├── internal ├── asset │ ├── file.go │ ├── files.go │ ├── json.go │ └── yaml.go ├── codegen │ ├── README.md │ ├── ast │ │ ├── assign.go │ │ ├── ast.go │ │ ├── ast_test.go │ │ ├── binary.go │ │ ├── builder.go │ │ ├── condition.go │ │ ├── dml.go │ │ ├── errcheck.go │ │ ├── expression.go │ │ ├── foreach.go │ │ ├── func.go │ │ ├── literal.go │ │ ├── options.go │ │ ├── scope.go │ │ └── star.go │ ├── column │ │ └── generator.go │ ├── doc.go │ ├── dql.go │ ├── entity.go │ ├── handler.go │ ├── index.go │ ├── options.go │ ├── plugin.go │ ├── registry.go │ ├── state.go │ ├── template.go │ └── tmpl │ │ ├── dql.sqlx │ │ ├── entity.gox │ │ ├── handler │ │ ├── handler.gox │ │ ├── handler_init.gox │ │ ├── has_key.gox │ │ ├── index.gox │ │ └── index_by.gox │ │ ├── input.gox │ │ ├── input_init.gox │ │ ├── input_validate.gox │ │ ├── output.gox │ │ └── plugin │ │ ├── checksum.gox │ │ ├── dependency.gox │ │ └── main.gox ├── converter │ ├── converter.go │ ├── init.go │ └── repeated.go ├── inference │ ├── column.go │ ├── doc.go │ ├── field.go │ ├── hint.go │ ├── import.go │ ├── parameter.go │ ├── parameter_test.go │ ├── selector.go │ ├── spec.go │ ├── state.go │ ├── struct.go │ ├── struct_test.go │ ├── table.go │ ├── tag.go │ ├── text.go │ └── type.go ├── msg │ ├── message.go │ └── messages.go ├── plugin │ ├── info.go │ ├── package.go │ ├── packages.go │ └── service.go ├── setter │ ├── ptr.go │ └── setter.go ├── tests │ ├── db.go │ └── log.go └── translator │ ├── README.md │ ├── async.go │ ├── cache.go │ ├── config.go │ ├── connection.go │ ├── const.go │ ├── contract.go │ ├── discovery.go │ ├── dml.go │ ├── doc.go │ ├── function.go │ ├── function │ ├── allownulls.go │ ├── batch_size.go │ ├── cache.go │ ├── cardinality.go │ ├── connector.go │ ├── fetch_strategy.go │ ├── function.go │ ├── init.go │ ├── limit.go │ ├── orderby.go │ ├── partition.go │ ├── publish_parent.go │ ├── registry.go │ └── relation_concurrency.go │ ├── input.go │ ├── mbus.go │ ├── oauth.go │ ├── output.go │ ├── parser │ ├── declaration.go │ ├── declarations.go │ ├── declarations_test.go │ ├── hint.go │ ├── import.go │ ├── iterable.go │ ├── lex.go │ ├── match.go │ ├── matcher.go │ ├── matchers │ │ ├── any.go │ │ ├── identity.go │ │ ├── ifblock.go │ │ ├── selector.go │ │ ├── terminator.go │ │ └── word.go │ ├── merge.go │ ├── sanitizer.go │ ├── selector.go │ ├── statement.go │ ├── template.go │ ├── template_test.go │ ├── text.go │ ├── types.go │ └── velty.go │ ├── predicate.go │ ├── repository.go │ ├── resource.go │ ├── rule.go │ ├── service.go │ ├── static.go │ ├── view.go │ ├── viewlet.go │ └── viewlets.go ├── logger ├── adapter.go ├── counter.go ├── default.go ├── logger.go └── time.go ├── mcp ├── extension │ ├── handler.go │ └── handler_test.go └── server.go ├── repository ├── async │ ├── config.go │ └── state.go ├── codegen.go ├── codegen │ ├── context.go │ ├── contract.gox │ └── register.gox ├── component.go ├── components.go ├── content │ ├── config.go │ ├── const.go │ └── content.go ├── contract │ ├── contract.go │ ├── dispatcher.go │ ├── input.go │ ├── meta.go │ ├── output.go │ ├── path.go │ ├── signature │ │ ├── header.go │ │ ├── service.go │ │ ├── service_test.go │ │ ├── signature.go │ │ └── testdata │ │ │ ├── vendor_details.yaml │ │ │ └── vendor_list.yaml │ └── status.go ├── handler │ └── handler.go ├── locator │ ├── async │ │ ├── keys │ │ │ ├── async.go │ │ │ └── types.go │ │ └── locator.go │ ├── component │ │ ├── component.go │ │ └── dispatcher │ │ │ └── disptacher.go │ ├── meta │ │ ├── keys │ │ │ ├── meta.go │ │ │ └── types.go │ │ └── locator.go │ └── output │ │ ├── filter.go │ │ ├── keys │ │ ├── output.go │ │ └── types.go │ │ ├── output.go │ │ └── response.go ├── logging │ ├── config.go │ └── logging.go ├── option.go ├── path │ ├── apikey.go │ ├── compression.go │ ├── container.go │ ├── cors.go │ ├── logger.go │ ├── service.go │ ├── service_test.go │ ├── snapshot.go │ └── testdata │ │ ├── .mete │ │ └── vendor_hauth.yaml │ │ ├── vars.yaml │ │ └── vendor_hauth.yaml ├── plugin │ ├── service.go │ └── snapshot.go ├── provider.go ├── redirect │ └── handler.go ├── registry.go ├── resource.go ├── resource │ ├── service.go │ └── snapshot.go ├── service.go ├── version │ ├── control.go │ └── resource.go └── warmup.go ├── service.go ├── service ├── auth │ ├── cognito │ │ └── service.go │ ├── config │ │ └── config.go │ ├── firebase │ │ └── service.go │ ├── jwt │ │ ├── cache.go │ │ ├── provider.go │ │ └── verifier.go │ ├── mock │ │ ├── config.go │ │ └── jwt │ │ │ ├── hmac.enc │ │ │ ├── private.enc │ │ │ └── public.enc │ ├── secret │ │ ├── resource.go │ │ └── service.go │ ├── service.go │ └── token │ │ └── authorization.go ├── const.go ├── dbms │ ├── doc.go │ ├── provider │ │ ├── bigquery │ │ │ └── sql.go │ │ ├── mysql │ │ │ └── sql.go │ │ ├── sql.go │ │ └── table.go │ └── service.go ├── executor │ ├── db.go │ ├── db_view.go │ ├── expand │ │ ├── bindings.go │ │ ├── data_unit.go │ │ ├── deref.go │ │ ├── evaluator.go │ │ ├── fn.go │ │ ├── fn_changed.go │ │ ├── fn_length.go │ │ ├── fn_new.go │ │ ├── fn_nop.go │ │ ├── fn_printer.go │ │ ├── fn_query.go │ │ ├── fn_response.go │ │ ├── fn_transform.go │ │ ├── fns_differ.go │ │ ├── http.go │ │ ├── init.go │ │ ├── options.go │ │ ├── parent.go │ │ ├── predicate.go │ │ ├── predicate_test.go │ │ ├── sql.go │ │ ├── state.go │ │ └── validator.go │ ├── extension │ │ ├── differ.go │ │ ├── mbus.go │ │ ├── options.go │ │ ├── response.go │ │ ├── session.go │ │ ├── sqlx.go │ │ └── validator.go │ ├── handler │ │ ├── auth.go │ │ ├── executor.go │ │ ├── http.go │ │ ├── iterator.go │ │ ├── locator │ │ │ └── handler.go │ │ ├── options.go │ │ ├── sqlx.go │ │ └── validator.go │ ├── mbus │ │ └── service.go │ ├── option.go │ ├── parser │ │ └── parser.go │ ├── sequencer │ │ ├── node.go │ │ ├── sequence.go │ │ ├── service.go │ │ ├── service_test.go │ │ ├── walker.go │ │ └── walker_test.go │ ├── service.go │ ├── session.go │ ├── sql.go │ ├── sqlx.go │ ├── stmt.go │ ├── stmt_template.go │ └── tx.go ├── jobs │ ├── inserter.go │ ├── internal │ │ ├── README.md │ │ └── rules │ │ │ ├── deactivate.sql │ │ │ ├── jobs.sql │ │ │ └── shared │ │ │ ├── input.sqlx │ │ │ ├── output.sqlx │ │ │ └── predicates.yaml │ ├── reader.go │ ├── resource.go │ ├── service.go │ └── updater.go ├── operator │ ├── async.go │ ├── executor.go │ ├── reader.go │ └── service.go ├── reader │ ├── README.md │ ├── events.go │ ├── example_test.go │ ├── handler │ │ └── handler.go │ ├── lifecycle.go │ ├── metadata │ │ ├── discover.go │ │ ├── discover_test.go │ │ ├── lex.go │ │ └── terminator.go │ ├── option.go │ ├── reflect.go │ ├── service.go │ ├── session.go │ ├── slice.go │ ├── sql.go │ ├── sql_meta.go │ ├── sql_option.go │ ├── sql_test.go │ ├── testdata │ │ ├── cases │ │ │ ├── case001_schema │ │ │ │ ├── populate_db │ │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ │ ├── case002_from │ │ │ │ ├── populate_db │ │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ │ ├── case003_exclude │ │ │ │ ├── populate_db │ │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ │ ├── case004_selector │ │ │ │ ├── populate_db │ │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ │ ├── case005_column_expression │ │ │ │ ├── populate_db │ │ │ │ │ └── foos.json │ │ │ │ └── resources.yaml │ │ │ ├── case006_client_selector │ │ │ │ ├── populate_db │ │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ │ ├── case007_one_to_one │ │ │ │ ├── populate_db │ │ │ │ │ ├── event_types.json │ │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ │ ├── case008_many_to_one │ │ │ │ ├── populate_db │ │ │ │ │ ├── accounts.json │ │ │ │ │ └── users.json │ │ │ │ └── resources.yaml │ │ │ ├── case009_without_column │ │ │ │ ├── populate_db │ │ │ │ │ ├── event_types.json │ │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ │ ├── case010_view_parameter │ │ │ │ ├── populate_db │ │ │ │ │ ├── accounts.json │ │ │ │ │ ├── datly_acl.json │ │ │ │ │ └── users.json │ │ │ │ └── resources.yaml │ │ │ ├── case011_read_all_one_to_one │ │ │ │ ├── populate_db │ │ │ │ │ ├── event_types.json │ │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ │ ├── case012_many_to_one │ │ │ │ ├── populate_db │ │ │ │ │ ├── accounts.json │ │ │ │ │ └── users.json │ │ │ │ └── resources.yaml │ │ │ ├── case012_read_all_many_to_one │ │ │ │ ├── populate_db │ │ │ │ │ ├── accounts.json │ │ │ │ │ └── users.json │ │ │ │ └── resources.yaml │ │ │ ├── case013_read_all_batch_size │ │ │ │ ├── populate_db │ │ │ │ │ └── articles.json │ │ │ │ ├── populate_other │ │ │ │ │ └── languages.json │ │ │ │ └── resources.yaml │ │ │ ├── case014_T_one_to_one │ │ │ │ ├── populate_db │ │ │ │ │ └── articles.json │ │ │ │ ├── populate_other │ │ │ │ │ └── languages.json │ │ │ │ └── resources.yaml │ │ │ ├── case015_path_parameter │ │ │ │ ├── populate_db │ │ │ │ │ └── users.json │ │ │ │ └── resources.yaml │ │ │ ├── case016_query_parameter │ │ │ │ ├── populate_other │ │ │ │ │ └── languages.json │ │ │ │ └── resources.yaml │ │ │ ├── case017_header_parameter │ │ │ │ ├── populate_db │ │ │ │ │ └── users.json │ │ │ │ └── resources.yaml │ │ │ ├── case018_cookie_parameter │ │ │ │ ├── populate_db │ │ │ │ │ └── users.json │ │ │ │ └── resources.yaml │ │ │ ├── case019_derive_columns │ │ │ │ ├── populate_db │ │ │ │ │ └── datly_acl.json │ │ │ │ └── resources.yaml │ │ │ ├── case020_derive_columns_relation │ │ │ │ ├── populate_db │ │ │ │ │ ├── event_types.json │ │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ │ ├── case021_on_fetch │ │ │ │ ├── populate_other │ │ │ │ │ ├── audiences.json │ │ │ │ │ └── deals.json │ │ │ │ └── resources.yaml │ │ │ ├── case022_types │ │ │ │ ├── populate_db │ │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ │ ├── case023_columns_codec │ │ │ │ ├── populate_db │ │ │ │ │ └── users.json │ │ │ │ └── resources.yaml │ │ │ └── case024_one_to_one_ns │ │ │ │ ├── populate_db │ │ │ │ ├── event_types.json │ │ │ │ └── events.json │ │ │ │ └── resources.yaml │ │ ├── datasets │ │ │ ├── dataset001_events │ │ │ │ ├── populate_db │ │ │ │ │ ├── event_types.json │ │ │ │ │ └── events.json │ │ │ │ └── populate_other │ │ │ │ │ └── event_types.json │ │ │ └── dataset002_nils │ │ │ │ └── populate_db │ │ │ │ └── events.json │ │ ├── db_config.yaml │ │ ├── db_schema.sql │ │ ├── other_config.yaml │ │ └── other_schema.sql │ └── time.go └── session │ ├── cache.go │ ├── copier.go │ ├── criteria │ ├── lex.go │ ├── matcher │ │ ├── identity.go │ │ ├── identity_test.go │ │ ├── integer.go │ │ ├── integer_test.go │ │ └── string.go │ ├── parse.go │ └── parse_test.go │ ├── expr.go │ ├── option.go │ ├── reader.go │ ├── selector.go │ ├── state.go │ ├── stater.go │ └── views.go ├── shared ├── args.go ├── combine.go ├── const.go ├── consts.go ├── deref.go ├── errors.go ├── http.go ├── keys.go ├── marshal.go ├── marshaller.go ├── matcher.go ├── module.go ├── not_empty.go ├── path.go ├── ref.go ├── sql.go └── text.go ├── utils ├── debug │ └── debug.go ├── formatter │ └── normalize.go ├── httputils │ ├── compress.go │ ├── headers.go │ ├── request.go │ ├── response.go │ └── violation.go └── types │ ├── accessors.go │ ├── accessors_test.go │ ├── inline.go │ ├── namer.go │ ├── object.go │ ├── reflect.go │ └── types.go ├── view ├── README.md ├── batch.go ├── cache.go ├── codec.go ├── collector.go ├── column.go ├── column │ └── discover.go ├── columns.go ├── config.go ├── connector.go ├── connectors.go ├── context │ └── context.go ├── definition.go ├── discover │ └── columns.go ├── docs.go ├── extension │ ├── LICENSE │ ├── codec │ │ ├── auth.go │ │ ├── bauth.go │ │ ├── cogito.go │ │ ├── criteria.go │ │ ├── csv.go │ │ ├── encode.go │ │ ├── filters.go │ │ ├── firebase.go │ │ ├── ints.go │ │ ├── json.go │ │ ├── jsontab.go │ │ ├── jsontab │ │ │ ├── service.go │ │ │ └── service_test.go │ │ ├── jwt.go │ │ ├── nil.go │ │ ├── options.go │ │ ├── strings.go │ │ ├── structql.go │ │ ├── timedif.go │ │ ├── timediff_test.go │ │ ├── transfer.go │ │ ├── transfer │ │ │ └── tag.go │ │ ├── transfer_test.go │ │ ├── urichksum.go │ │ ├── urichksum_test.go │ │ ├── urirewrite.go │ │ ├── urirewrite_test.go │ │ ├── velty.go │ │ ├── xmlfilter.go │ │ ├── xmlfilter │ │ │ ├── service.go │ │ │ └── service_test.go │ │ ├── xmltab.go │ │ └── xmltab │ │ │ ├── service.go │ │ │ └── service_test.go │ ├── handler │ │ ├── load_delimited.go │ │ ├── loader.go │ │ └── proxy.go │ ├── init.go │ ├── marshaller │ │ └── json.go │ ├── plugin.go │ ├── predicates.go │ └── registry.go ├── keywords │ ├── context.go │ ├── fn.go │ ├── index.go │ └── keywords.go ├── match.go ├── mbus.go ├── metric.go ├── names.go ├── option.go ├── partition.go ├── pool.go ├── predicate.go ├── relation.go ├── resource.go ├── resourslet.go ├── sql.go ├── sql_test.go ├── state.go ├── state │ ├── async.go │ ├── cardinality.go │ ├── codec.go │ ├── docs.go │ ├── embeder.go │ ├── handler.go │ ├── hook.go │ ├── kind.go │ ├── kind │ │ ├── locator.go │ │ └── locator │ │ │ ├── body.go │ │ │ ├── constants.go │ │ │ ├── context.go │ │ │ ├── cookie.go │ │ │ ├── data.go │ │ │ ├── env.go │ │ │ ├── factory.go │ │ │ ├── form.go │ │ │ ├── generator.go │ │ │ ├── header.go │ │ │ ├── http.go │ │ │ ├── init.go │ │ │ ├── locators.go │ │ │ ├── marshaller.go │ │ │ ├── object.go │ │ │ ├── options.go │ │ │ ├── parameter.go │ │ │ ├── path.go │ │ │ ├── query.go │ │ │ ├── registry.go │ │ │ ├── repeated.go │ │ │ ├── state.go │ │ │ └── transient.go │ ├── location.go │ ├── parameter.go │ ├── parameters.go │ ├── predicate.go │ ├── predicate │ │ ├── filter.go │ │ └── filter_type.go │ ├── resource.go │ ├── schema.go │ ├── type.go │ └── types.go ├── substitutes.go ├── summary.go ├── tag.go ├── tags │ ├── codec.go │ ├── codec_test.go │ ├── desription.go │ ├── handler.go │ ├── link.go │ ├── parameter.go │ ├── parameter_test.go │ ├── parser.go │ ├── predicate.go │ ├── predicate_test.go │ ├── sql.go │ ├── tag.go │ ├── testdata │ │ └── foo.sql │ ├── view.go │ └── view_test.go ├── template.go ├── template │ ├── any.go │ ├── builder.go │ ├── lex.go │ ├── parser.go │ ├── parser_test.go │ └── value.go ├── time.go ├── types.go ├── view.go └── views.go └── warmup ├── cache.go ├── cache_test.go └── testdata ├── case001 ├── populate │ └── events.json └── resource.yaml ├── case002 ├── populate │ └── events.json └── resource.yaml ├── case003 ├── populate │ └── events.json └── resource.yaml ├── case004 ├── populate │ └── events.json └── resource.yaml ├── case005 ├── populate │ └── events.json └── resource.yaml ├── db_config.yaml └── db_schema.sql /.gcloudignore: -------------------------------------------------------------------------------- 1 | e2e 2 | e2e/ 3 | .idea 4 | .gcloudignore 5 | .git 6 | .gitignore 7 | *.yaml 8 | *.md 9 | secrets.json -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | secrets.json 3 | *.db 4 | local_test.go 5 | vendor 6 | datly 7 | other 8 | mydb 9 | tmp/ 10 | *.gz 11 | .DS_Store 12 | autogen 13 | dql 14 | dql 15 | *.iml 16 | *.so 17 | logs 18 | .extension 19 | .datly 20 | *.zip 21 | local -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Viant, inc. datly 2 | Copyright 2012-2020 Viant 3 | 4 | This product includes software developed at 5 | Viant (http://viantinc.com/) 6 | 7 | -------------------------------------------------------------------------------- /Version: -------------------------------------------------------------------------------- 1 | v0.20.2 -------------------------------------------------------------------------------- /cloudfunctions.go: -------------------------------------------------------------------------------- 1 | package datly 2 | 3 | import ( 4 | "github.com/viant/datly/gateway/runtime/gcf" 5 | "net/http" 6 | ) 7 | 8 | func Handle(w http.ResponseWriter, r *http.Request) { 9 | gcf.Handle(w, r) 10 | } 11 | -------------------------------------------------------------------------------- /cmd/command/bundle.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "context" 5 | "github.com/viant/afs/cache" 6 | "github.com/viant/afs/matcher" 7 | soption "github.com/viant/afs/option" 8 | "github.com/viant/datly/cmd/options" 9 | "github.com/viant/datly/gateway" 10 | ) 11 | 12 | func (s *Service) BundleRules(ctx context.Context, bundle *options.Bundle) error { 13 | cacheSetting := soption.WithCache(gateway.PackageFile, "gzip") 14 | return cache.Package(context.Background(), bundle.Source, bundle.RuleDest, 15 | cacheSetting, 16 | matcher.WithExtExclusion(".so", "so", ".gz", "gz"), 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /cmd/command/cache.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "github.com/viant/datly/cmd/options" 8 | "github.com/viant/datly/gateway/warmup" 9 | ) 10 | 11 | func (s *Service) WarmupCache(ctx context.Context, cache *options.CacheWarmup) error { 12 | srv, err := s.run(ctx, &cache.Run) 13 | if err != nil { 14 | return err 15 | } 16 | response := warmup.PreCache(ctx, srv.Service.PreCachables, cache.WarmupURIs...) 17 | data, _ := json.Marshal(response) 18 | fmt.Printf("%s\n", data) 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /cmd/command/router.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | "github.com/viant/datly/cmd/options" 6 | ) 7 | 8 | func (s *Service) configureRouter(opts *options.Options) error { 9 | if err := s.ensureTranslator(opts); err != nil { 10 | return fmt.Errorf("failed to create translator: %v", err) 11 | } 12 | return nil 13 | } 14 | -------------------------------------------------------------------------------- /cmd/command/tmpl/README.md: -------------------------------------------------------------------------------- 1 | ## Custom datly extension 2 | 3 | ### Initialise datly rule repository 4 | 5 | ```bash 6 | datly init -c= -j -r -c -d=runtime/dev 7 | ``` 8 | 9 | ### 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /cmd/command/tmpl/ext/go.modx: -------------------------------------------------------------------------------- 1 | module github.com/viant/xdatly/extension 2 | 3 | go 1.21 4 | 5 | require $module v0.0.0-00010101000000-000000000000 6 | 7 | replace $module => $modulePath 8 | -------------------------------------------------------------------------------- /cmd/command/tmpl/ext/init.gox: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | 4 | import _ "$module" -------------------------------------------------------------------------------- /cmd/command/tmpl/pkg/bootstrap/bootstrap.gox: -------------------------------------------------------------------------------- 1 | package bootstrap 2 | 3 | import ( 4 | "github.com/viant/xdatly/types/core" 5 | "${impModule}/dependency/checksum" 6 | "reflect" 7 | ) 8 | 9 | 10 | var PackageName = "bootstrap" 11 | 12 | func init() { 13 | core.RegisterType(PackageName, "Bootstrap", reflect.TypeOf(struct{}{}), checksum.GeneratedTime) 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /cmd/command/tmpl/pkg/checksum/init.gox: -------------------------------------------------------------------------------- 1 | //Code generated by DATLY. DO NOT EDIT. GeneratedTime will be updated whenever new plugin was generated. 2 | //Please use GeneratedTime to Register types. It will help to keep types synchronized when using plugins. 3 | 4 | package checksum 5 | 6 | import "time" 7 | 8 | var GeneratedTime, _ = time.Parse(time.RFC3339, "${generatedAt}") 9 | -------------------------------------------------------------------------------- /cmd/command/tmpl/pkg/dependency/init.gox: -------------------------------------------------------------------------------- 1 | // Code generated by DATLY. Append sideefect imports here. 2 | package dependency 3 | 4 | import ( 5 | _ "${impModule}/bootstrap" 6 | ) 7 | -------------------------------------------------------------------------------- /cmd/command/tmpl/pkg/init.gox: -------------------------------------------------------------------------------- 1 | package $moduleName 2 | 3 | import ( 4 | _ "${impModule}/dependency" 5 | ) -------------------------------------------------------------------------------- /cmd/command/tmpl/pkg/plugin/init.gox: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "${impModule}/dependency" 5 | ) -------------------------------------------------------------------------------- /cmd/env/cloud.go: -------------------------------------------------------------------------------- 1 | package env 2 | 3 | const ( 4 | BuildTypeKindLambda BuildTypeKind = "aws-lambda" 5 | BuildTypeKindAPIGW BuildTypeKind = "apigw" 6 | BuildTypeKindLambdaSQS BuildTypeKind = "aws-sqs" 7 | BuildTypeKindLambdaS3 BuildTypeKind = "aws-s3" 8 | ) 9 | 10 | type BuildTypeKind string 11 | -------------------------------------------------------------------------------- /cmd/env/debug.go: -------------------------------------------------------------------------------- 1 | //go:build debug 2 | 3 | package env 4 | 5 | import ( 6 | "github.com/viant/datly/utils/debug" 7 | delete2 "github.com/viant/sqlx/io/delete" 8 | "github.com/viant/sqlx/io/insert" 9 | "github.com/viant/sqlx/io/read" 10 | "github.com/viant/sqlx/io/update" 11 | ) 12 | 13 | func init() { 14 | debug.SetEnabled(true) 15 | insert.ShowSQL(true) 16 | update.ShowSQL(true) 17 | read.ShowSQL(true) 18 | delete2.ShowSQL(true) 19 | } 20 | -------------------------------------------------------------------------------- /cmd/env/metadata.go: -------------------------------------------------------------------------------- 1 | package env 2 | 3 | import ( 4 | "github.com/viant/pgo/build" 5 | "runtime" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | var ( 11 | GoVersion string 12 | BuildTime time.Time 13 | BuildType BuildTypeKind 14 | ) 15 | 16 | func init() { 17 | GoVersion = strings.Replace(runtime.Version(), "go", "", 1) 18 | aRuntime := build.Runtime{} 19 | aRuntime.Init() 20 | } 21 | -------------------------------------------------------------------------------- /cmd/options/args.go: -------------------------------------------------------------------------------- 1 | package options 2 | 3 | import "strings" 4 | 5 | type Arguments []string 6 | 7 | func (a Arguments) IsHelp() bool { 8 | for _, arg := range a { 9 | if arg == "-h" { 10 | return true 11 | } 12 | } 13 | return false 14 | } 15 | 16 | func (a Arguments) IsLegacy() bool { 17 | for _, arg := range a { 18 | if arg == "-Lg" { 19 | return true 20 | } 21 | } 22 | return false 23 | } 24 | func (a Arguments) SubMode() bool { 25 | if len(a) == 0 { 26 | return false 27 | } 28 | return !strings.HasPrefix(a[0], "-") 29 | } 30 | -------------------------------------------------------------------------------- /cmd/options/bundle.go: -------------------------------------------------------------------------------- 1 | package options 2 | 3 | type Bundle struct { 4 | Source string `short:"s" long:"src" description:"datly rule repository " ` 5 | RuleDest string `short:"d" long:"dest" description:"datly rule repository rewrite deployment dest ie.: s3://vaint-e2e-config/datly-xxx/" ` 6 | } 7 | 8 | func (b *Bundle) Init() error { 9 | b.Source = ensureAbsPath(b.Source) 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /cmd/options/conn.go: -------------------------------------------------------------------------------- 1 | package options 2 | 3 | type Connector struct { 4 | Connectors []string `short:"c" long:"conn" description:"name|driver|dsn|secretUrl|key" ` 5 | } 6 | 7 | func (c *Connector) Init() { 8 | if len(c.Connectors) == 0 { 9 | return 10 | } 11 | for i, con := range c.Connectors { 12 | c.Connectors[i] = expandHomeDir(con) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cmd/options/ext/init/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/cmd/options/ext/init/README.md -------------------------------------------------------------------------------- /cmd/options/init.go: -------------------------------------------------------------------------------- 1 | package options 2 | 3 | import "context" 4 | 5 | type Init struct { 6 | Project string `short:"p" long:"proj" description:"project location"` 7 | Repository 8 | CacheProvider 9 | } 10 | 11 | func (i *Init) Init(ctx context.Context) error { 12 | i.Project = ensureAbsPath(i.Project) 13 | i.Repository.Init(ctx, i.Project) 14 | if i.Port == nil { 15 | port := 8080 16 | i.Port = &port 17 | } 18 | return i.CacheProvider.Init() 19 | } 20 | -------------------------------------------------------------------------------- /cmd/options/mbus.go: -------------------------------------------------------------------------------- 1 | package options 2 | 3 | type Mbus struct { 4 | MBuses []string `short:"b" long:"mbus" description:"name|vendor|resourceType|uri[|region|secretURL|secretKey]" ` 5 | } 6 | 7 | func (c *Mbus) Init() { 8 | if len(c.MBuses) == 0 { 9 | return 10 | } 11 | for i, con := range c.MBuses { 12 | c.MBuses[i] = expandHomeDir(con) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cmd/options/router.go: -------------------------------------------------------------------------------- 1 | package options 2 | 3 | type Router struct { 4 | RouterURL string `json:",omitempty" yaml:",omitempty"` 5 | URL string `json:",omitempty" yaml:",omitempty"` 6 | Routes []struct { 7 | SourceURL string 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /cmd/options/shared.go: -------------------------------------------------------------------------------- 1 | package options 2 | -------------------------------------------------------------------------------- /cmd/options/touch.go: -------------------------------------------------------------------------------- 1 | package options 2 | 3 | import "github.com/viant/afs/url" 4 | 5 | type Touch struct { 6 | Repo string `short:"r" long:"repo" description:"datly rule repository location" ` 7 | RoutesURL string 8 | } 9 | 10 | func (t *Touch) Init() { 11 | t.Repo = ensureAbsPath(t.Repo) 12 | t.RoutesURL = url.Join(t.Repo, "Datly/routes") 13 | } 14 | -------------------------------------------------------------------------------- /cmd/options/translate.go: -------------------------------------------------------------------------------- 1 | package options 2 | 3 | import "context" 4 | 5 | type Translate struct { 6 | Rule 7 | Repository 8 | } 9 | 10 | func (d *Translate) Init(ctx context.Context) error { 11 | if err := d.Rule.Init(); err != nil { 12 | return err 13 | } 14 | return d.Repository.Init(ctx, d.Project) 15 | } 16 | -------------------------------------------------------------------------------- /cmd/resource/mysql.json: -------------------------------------------------------------------------------- 1 | {"Username":"root","EncryptedPassword":"AAAAAAAAAAAT/CNE/kYf7Q=="} -------------------------------------------------------------------------------- /doc/asset/datly_arch.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/doc/asset/datly_arch.drawio.png -------------------------------------------------------------------------------- /doc/asset/datly_executor.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/doc/asset/datly_executor.drawio.png -------------------------------------------------------------------------------- /doc/asset/datly_reader.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/doc/asset/datly_reader.drawio.png -------------------------------------------------------------------------------- /doc/asset/raw_credentials.json: -------------------------------------------------------------------------------- 1 | {"Username": "myUser", "Password": "myPassword", "Endpoint": "myDbEndpoint"} -------------------------------------------------------------------------------- /e2e/cloud/jwt/private.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/e2e/cloud/jwt/private.enc -------------------------------------------------------------------------------- /e2e/cloud/jwt/public.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/e2e/cloud/jwt/public.enc -------------------------------------------------------------------------------- /e2e/local/datastore/dyndb/populate/USER_ACL.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"USER_ID": 1,"ACCOUNT_ID": 1, "ROLE": ["READ_ONLY", "PERF_VIEWER"], "PERMISSION": ["FEATURE1", "FEATUREN"], "Entities": {"GROUP1": [1,2,3,4,5,6]}}, 3 | {"USER_ID": 2,"ACCOUNT_ID": 1, "ROLE": ["ADMIN", "PERF_VIEWER"], "PERMISSION": ["FEATURE1", "FEATURE2", "FEATUREN"], "Entities": {"GROUP1": [1,2,3,4,5,6]}} 4 | ] -------------------------------------------------------------------------------- /e2e/local/datastore/dyndb/schema.ddl: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS USER_ACL; 2 | CREATE TABLE USER_ACL ( 3 | USER_ID INT HASH KEY, 4 | ACCOUNT_ID INT RANGE KEY 5 | ); 6 | -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/BAR.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "ID": 1, 5 | "NAME": "BAR - 1", 6 | "PRICE": 1.123456780123456780123456780, 7 | "TAX": 0.01123456780123456780123456780 8 | }, 9 | { 10 | "ID": 2, 11 | "NAME": "BAR - 2", 12 | "PRICE": 2.23456780123456780123456789, 13 | "TAX": 0.0223456780123456780123456789 14 | }, 15 | { 16 | "ID": 3, 17 | "NAME": "BAR - 3", 18 | "PRICE": 3.3456780123456780123456780, 19 | "TAX": 0.033456780123456780123456780 20 | } 21 | ] -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/CITY.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "ID": 1, 5 | "NAME": "district - 1 / city - 1", 6 | "ZIP_CODE": "12-345", 7 | "DISTRICT_ID": 1 8 | }, 9 | { 10 | "ID": 2, 11 | "NAME": "district - 2 / city - 1", 12 | "DISTRICT_ID": 2, 13 | "ZIP_CODE": "23-456" 14 | }, 15 | { 16 | "ID": 3, 17 | "NAME": "district - 1 / city - 2", 18 | "DISTRICT_ID": 1, 19 | "ZIP_CODE": "34-567" 20 | }, 21 | { 22 | "ID": 4, 23 | "NAME": "district - 1 / city - 3", 24 | "DISTRICT_ID": 1, 25 | "ZIP_CODE": "45_678" 26 | } 27 | ] -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/DATLY_JOBS.json: -------------------------------------------------------------------------------- 1 | [{}] -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/DISTRICT.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "ID": 1, 5 | "NAME": "district - 1" 6 | }, 7 | { 8 | "ID": 2, 9 | "NAME": "district - 2" 10 | }, 11 | { 12 | "ID": 3, 13 | "NAME": "district - 3" 14 | } 15 | ] -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/EVENTS.json: -------------------------------------------------------------------------------- 1 | [ 2 | {} 3 | ] -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/EVENTS_PERFORMANCE.json: -------------------------------------------------------------------------------- 1 | [ 2 | {} 3 | ] -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/PRODUCT_JN.json: -------------------------------------------------------------------------------- 1 | [ 2 | {} 3 | ] -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/TEAM.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "ID": 1, 5 | "NAME": "Team - 1", 6 | "ACTIVE": true 7 | }, 8 | { 9 | "ID": 2, 10 | "NAME": "Team - 2", 11 | "ACTIVE": true 12 | }, 13 | { 14 | "ID": 3, 15 | "NAME": "Team - 3", 16 | "ACTIVE": true 17 | }, 18 | { 19 | "ID": 1000000, 20 | "NAME": "Team - 1000000", 21 | "ACTIVE": true 22 | } 23 | ] -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/USER_METADATA.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "ID": 1, 5 | "USER_ID": 1, 6 | "IS_ENABLED": true, 7 | "IS_ACTIVATED": false 8 | }, 9 | { 10 | "ID": 2, 11 | "USER_ID": 2, 12 | "IS_ENABLED": false, 13 | "IS_ACTIVATED": true 14 | } 15 | ] -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/USER_TEAM.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "ID": 1, 5 | "TEAM_ID": 1, 6 | "USER_ID": 1 7 | }, 8 | { 9 | "ID": 2, 10 | "TEAM_ID": 1, 11 | "USER_ID": 2 12 | }, 13 | { 14 | "ID": 3, 15 | "TEAM_ID": 2, 16 | "USER_ID": 1 17 | } 18 | ] -------------------------------------------------------------------------------- /e2e/local/datastore/mysql/populate/VENDOR.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "ID": 1, 5 | "NAME": "Vendor 1", 6 | "ACCOUNT_ID": 100, 7 | "CREATED": "", 8 | "USER_CREATED": 1 9 | }, 10 | { 11 | "ID": 2, 12 | "NAME": "Vendor 2", 13 | "ACCOUNT_ID": 101, 14 | "CREATED": "", 15 | "USER_CREATED": 2 16 | }, 17 | { 18 | "ID": 3, 19 | "NAME": "Vendor 3", 20 | "ACCOUNT_ID": 100, 21 | "CREATED": "", 22 | "USER_CREATED": 1 23 | } 24 | ] -------------------------------------------------------------------------------- /e2e/local/jwt/hmac.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/e2e/local/jwt/hmac.enc -------------------------------------------------------------------------------- /e2e/local/jwt/private.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/e2e/local/jwt/private.enc -------------------------------------------------------------------------------- /e2e/local/jwt/public.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/e2e/local/jwt/public.enc -------------------------------------------------------------------------------- /e2e/local/regression/cases/001_one_to_many/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "@indexBy@": "id" 4 | }, 5 | { 6 | "id": 1, 7 | "name": "Vendor 1", 8 | "products": [ 9 | { 10 | "@indexBy@": "id" 11 | }, 12 | { 13 | "id": 1, 14 | "name": "V1 Product 1", 15 | "userCreated": 1 16 | }, 17 | { 18 | "id": 2, 19 | "name": "V1 Product 2", 20 | "userCreated": 1 21 | } 22 | ] 23 | }, 24 | { 25 | "id": 2, 26 | "name": "Vendor 2" 27 | }, 28 | { 29 | "id": 3, 30 | "name": "Vendor 3" 31 | } 32 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/001_one_to_many/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendor_list.dql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/002_uri_param/doc.yaml: -------------------------------------------------------------------------------- 1 | Parameters: 2 | vendorID: custom vendorID description 3 | 4 | Columns: 5 | vendor.ID: "vendor ID column description" -------------------------------------------------------------------------------- /e2e/local/regression/cases/002_uri_param/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendor_details.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/002_uri_param/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | expect: $LoadData('${parentPath}/expect.json') 4 | pipeline: 5 | 6 | test: 7 | action: http/runner:send 8 | requests: 9 | - Method: GET 10 | URL: http://127.0.0.1:8080/v1/api/dev/vendors/2 11 | Expect: 12 | Code: 200 13 | JSONBody: $expect 14 | 15 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/002_uri_param/vendor_details_vendor.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM VENDOR t WHERE t.ID = $vendorID -------------------------------------------------------------------------------- /e2e/local/regression/cases/003_oauth/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 2, 4 | "name": "Vendor 2", 5 | "firstName": "Developer", 6 | "products": [ 7 | { 8 | "@indexBy@": "id" 9 | }, 10 | { 11 | "id": 3, 12 | "name": "V2 Product 1", 13 | "userCreated": 2 14 | }, 15 | { 16 | "id": 4, 17 | "name": "V2 Product 2", 18 | "userCreated": 2 19 | }, 20 | { 21 | "id": 5, 22 | "name": "V2 Product 3", 23 | "userCreated": 2 24 | } 25 | ] 26 | } 27 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/003_oauth/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendor_auth.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/004_update/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 2, 4 | "name": "Vendor 2", 5 | "products": [ 6 | { 7 | "@indexBy@": "id" 8 | }, 9 | { 10 | "id": 3, 11 | "name": "V2 Product 1", 12 | "userCreated": 2 13 | }, 14 | { 15 | "id": 4, 16 | "name": "V2 Product 2", 17 | "userCreated": 2 18 | }, 19 | { 20 | "id": 5, 21 | "name": "V2 Product 3", 22 | "userCreated": 2 23 | } 24 | ] 25 | } 26 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/004_update/expect/PRODUCT.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "ID": 1, 5 | "NAME": "V1 Product 1", 6 | "VENDOR_ID": 1, 7 | "STATUS": 2, 8 | "USER_CREATED": 1 9 | } 10 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/004_update/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/product_update.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/005_sumary/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendor_meta.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/005_sumary/test.yaml: -------------------------------------------------------------------------------- 1 | 2 | pipeline: 3 | 4 | test: 5 | action: http/runner:send 6 | requests: 7 | - Method: GET 8 | URL: http://127.0.0.1:8080/v1/api/dev/meta/vendors 9 | Expect: 10 | Code: 200 11 | JSONBody: 12 | status: ok 13 | meta: 14 | pageCnt: 1 15 | cnt: 3 -------------------------------------------------------------------------------- /e2e/local/regression/cases/006_tree/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/user_tree.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/006_tree/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | expect: $LoadJSON('${parentPath}/expect.json') 4 | 5 | pipeline: 6 | 7 | test: 8 | action: http/runner:send 9 | requests: 10 | - Method: GET 11 | URL: http://127.0.0.1:8080/v1/api/dev/users/ 12 | Expect: 13 | Code: 200 14 | JSONBody: $expect 15 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/006_tree/user_tree.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"users/"} */ 2 | SELECT user.* EXCEPT MGR_ID 3 | FROM (SELECT t.* FROM USER t ) user /* {"Self":{"Holder":"Team", "Child":"ID", "Parent":"MGR_ID" }} */ 4 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/007_child_meta/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/child_meta.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/007_child_meta/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | expect: $LoadJSON('${parentPath}/expect.json') 4 | 5 | pipeline: 6 | 7 | test: 8 | action: http/runner:send 9 | requests: 10 | - Method: GET 11 | URL: http://127.0.0.1:8080/v1/api/dev/meta/vendors-nested 12 | Expect: 13 | Code: 200 14 | JSONBody: $expect -------------------------------------------------------------------------------- /e2e/local/regression/cases/008_record_pagination/district_pagination.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"meta/districts"} */ 2 | 3 | #set( $_ = $Page(query/page).Optional().QuerySelector('districts')) 4 | #set( $_ = $Data(output/view).Embed()) 5 | 6 | 7 | SELECT districts.*, 8 | cities.* 9 | FROM (SELECT t.* FROM DISTRICT t WHERE 1 = 1 AND ID IN ($IDs)) districts 10 | JOIN (SELECT * FROM CITY t) cities /* {"Selector": { "Limit": 2 } } */ ON districts.ID = cities.DISTRICT_ID 11 | 12 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/008_record_pagination/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/district_pagination.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/008_record_pagination/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | expect: $LoadJSON('${parentPath}/expect.json') 4 | 5 | pipeline: 6 | 7 | test: 8 | action: http/runner:send 9 | requests: 10 | - Method: GET 11 | URL: http://127.0.0.1:8080/v1/api/dev/meta/districts?IDs=1,2 12 | Expect: 13 | Code: 200 14 | JSONBody: $expect -------------------------------------------------------------------------------- /e2e/local/regression/cases/009_apikey/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 2, 4 | "name": "Vendor 2", 5 | "products": [ 6 | { 7 | "@indexBy@": "id" 8 | }, 9 | { 10 | "id": 3, 11 | "name": "V2 Product 1", 12 | "userCreated": 2 13 | }, 14 | { 15 | "id": 4, 16 | "name": "V2 Product 2", 17 | "userCreated": 2 18 | }, 19 | { 20 | "id": 5, 21 | "name": "V2 Product 3", 22 | "userCreated": 2 23 | } 24 | ] 25 | } 26 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/009_apikey/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendor_apikey.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/010_codecs/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Vendor 1", 5 | "accountId": 100, 6 | "userCreated": 1 7 | }, 8 | { 9 | "id": 2, 10 | "name": "Vendor 2", 11 | "accountId": 101, 12 | "userCreated": 2 13 | } 14 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/010_codecs/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendors_codec.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/010_codecs/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | expect: $LoadJSON('${parentPath}/expect.json') 4 | 5 | pipeline: 6 | 7 | test: 8 | action: http/runner:send 9 | requests: 10 | - Method: GET 11 | URL: http://127.0.0.1:8080/v1/api/dev/vendors-codec?vendorIDs=1,2 12 | Expect: 13 | Code: 200 14 | JSONBody: $expect -------------------------------------------------------------------------------- /e2e/local/regression/cases/010_codecs/vendors_codec.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"vendors-codec/"} */ 2 | 3 | #set( $_ = $Data(output/view).Embed()) 4 | 5 | SELECT vendor.* 6 | FROM (SELECT * FROM VENDOR t WHERE t.ID IN ($vendorIDs) ) vendor -------------------------------------------------------------------------------- /e2e/local/regression/cases/011_env/environment.sql: -------------------------------------------------------------------------------- 1 | /* { "URI":"vendors-env/", "Const": { "Vendor": "VENDOR", "Product": "PRODUCT" } } */ 2 | 3 | #set( $_ = $Data(output/view).Embed()) 4 | 5 | SELECT vendor.*, 6 | products.* 7 | FROM (SELECT * FROM $Vendor t WHERE t.ID IN ($vendorIDs) AND 2 = 2) vendor /* { "AllowNulls": true } */ 8 | JOIN (SELECT * FROM $Product t WHERE 2 = 2) products /* { "AllowNulls": true } */ ON products.VENDOR_ID = vendor.ID -------------------------------------------------------------------------------- /e2e/local/regression/cases/011_env/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/environment.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/011_env/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | expect: $LoadJSON('${parentPath}/expect.json') 4 | 5 | pipeline: 6 | printHello: 7 | action: print 8 | message: hello action 1 9 | 10 | test: 11 | action: http/runner:send 12 | requests: 13 | - Method: GET 14 | URL: http://127.0.0.1:8080/v1/api/dev/vendors-env?vendorIDs=1,2 15 | Expect: 16 | Code: 200 17 | JSONBody: $expect 18 | 19 | info: 20 | action: print 21 | message: $AsJSON($test) -------------------------------------------------------------------------------- /e2e/local/regression/cases/012_meta_format/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/meta_format.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/012_meta_format/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | expect: $LoadJSON('${parentPath}/expect.json') 4 | 5 | pipeline: 6 | 7 | test: 8 | action: http/runner:send 9 | requests: 10 | - Method: GET 11 | URL: http://127.0.0.1:8080/v1/api/dev/meta/vendors-format 12 | Expect: 13 | Code: 200 14 | JSONBody: $expect -------------------------------------------------------------------------------- /e2e/local/regression/cases/013_col_in/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendor_col_in.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/013_col_in/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/col/vendors/ 10 | Expect: 11 | Code: 200 12 | 13 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/014_header_params/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 2, 4 | "name": "Vendor 2", 5 | "products": [ 6 | { 7 | "@indexBy@": "id" 8 | }, 9 | { 10 | "id": 3, 11 | "name": "V2 Product 1", 12 | "userCreated": 2 13 | }, 14 | { 15 | "id": 4, 16 | "name": "V2 Product 2", 17 | "userCreated": 2 18 | }, 19 | { 20 | "id": 5, 21 | "name": "V2 Product 3", 22 | "userCreated": 2 23 | } 24 | ] 25 | } 26 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/014_header_params/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/header_vendors.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/014_header_params/header_vendors.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"headers/vendors"} */ 2 | 3 | #set( $_ = $Data(output/view).Embed()) 4 | 5 | SELECT vendor.*, 6 | products.* EXCEPT VENDOR_ID 7 | FROM (SELECT * FROM VENDOR t WHERE t.ID = $vendorID /* {"Kind": "header", "Location": "Vendor-Id"} */ ) vendor 8 | JOIN (SELECT * FROM PRODUCT t) products ON products.VENDOR_ID = vendor.ID -------------------------------------------------------------------------------- /e2e/local/regression/cases/014_header_params/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | expect: $LoadData('${parentPath}/expect.json') 4 | pipeline: 5 | 6 | test: 7 | action: http/runner:send 8 | requests: 9 | - Method: GET 10 | URL: http://127.0.0.1:8080/v1/api/dev/headers/vendors 11 | Header: 12 | Vendor-Id: ["2"] 13 | Expect: 14 | Code: 200 15 | JSONBody: $expect 16 | 17 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/015_index_by/expect/TEAM.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "ID": 1, 5 | "NAME": "Team - 1", 6 | "ACTIVE": true 7 | }, 8 | { 9 | "ID": 2, 10 | "NAME": "Team - 2", 11 | "ACTIVE": true 12 | }, 13 | { 14 | "ID": 3, 15 | "NAME": "Team - 3", 16 | "ACTIVE": false 17 | } 18 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/015_index_by/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/user_team.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/016_team_delete/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/team.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/016_team_delete/team.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"team/{teamID}", 2 | "Method": "DELETE" 3 | } */ 4 | 5 | DELETE FROM TEAM WHERE ID = ${teamID} 6 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/016_team_delete/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: DELETE 9 | URL: http://127.0.0.1:8080/v1/api/dev/team/1000000 10 | Expect: 11 | Code: 200 12 | 13 | checkDb: 14 | action: 'dsunit:query' 15 | datastore: dev 16 | SQL: 'SELECT COUNT(*) AS NUM_RECORDS FROM (SELECT 1 FROM TEAM WHERE ID = 1000000) T' 17 | expect: 18 | - NUM_RECORDS: 0 -------------------------------------------------------------------------------- /e2e/local/regression/cases/017_generate_post_basic_one/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@" 3 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/017_generate_post_basic_one/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "name": "017_ Custom name", 4 | "quantity": 25 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/017_generate_post_basic_one/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/post_basic_one.sql", 4 | "Args": "-G=post" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/017_generate_post_basic_one/post_basic_one.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI": "basic/events", "Method": "POST" 3 | } */ 4 | 5 | 6 | #set($_ = $Events(body/).Cardinality('One').Tag('anonymous:"true"')) 7 | #set($_ = $Events(body/).Output().Tag('anonymous:"true"')) 8 | 9 | 10 | SELECT events.* 11 | FROM (SELECT * FROM EVENTS) events 12 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/018_generate_post_basic_many/expect_t0.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "@exists@" 4 | } 5 | ] 6 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/018_generate_post_basic_many/expect_t1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "@exists@", 4 | "name": "018_ " 5 | }, 6 | { 7 | "id": "@exists@", 8 | "name": "018_ " 9 | } 10 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/018_generate_post_basic_many/expect_t2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "@exists@", 4 | "name": "018_ Custom - 1" 5 | }, 6 | { 7 | "id": "@exists@", 8 | "name": "018_ Custom - 2" 9 | } 10 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/018_generate_post_basic_many/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/post_basic_many.sql", 4 | "Args": "-G=post" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/018_generate_post_basic_many/post_basic_many.sql: -------------------------------------------------------------------------------- 1 | /* {"URI": "basic/events-many", "Method": "POST" 2 | } */ 3 | 4 | #set($_ = $Events(body/).Cardinality('Many').Tag('anonymous:"true"')) 5 | #set($_ = $Events(body/).Output().Tag('anonymous:"true"')) 6 | 7 | 8 | SELECT events.* 9 | FROM (SELECT * FROM EVENTS) events 10 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/019_generate_post_comprehensive_many/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "data": [ 4 | { 5 | "id": "@exists@" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/019_generate_post_comprehensive_many/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "data": [ 4 | { 5 | "id": "@exists@" 6 | }, 7 | { 8 | "id": "@exists@" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/019_generate_post_comprehensive_many/expect_t2.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "data": [ 4 | { 5 | "id": "@exists@", 6 | "name": "019_ Custom - 1" 7 | }, 8 | { 9 | "id": "@exists@", 10 | "name": "019_ Custom - 2" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/019_generate_post_comprehensive_many/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/post_comprehensive_many.sql", 4 | "Args": "-G=post" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/019_generate_post_comprehensive_many/post_comprehensive_many.sql: -------------------------------------------------------------------------------- 1 | /* {"URI": "comprehensive/events-many", "Method": "POST" } */ 2 | 3 | 4 | #set($_ = $Events(body/Data).Cardinality('Many')) 5 | #set($_ = $Status(output/status).Tag('anonymous:"true"')) 6 | #set($_ = $Data(body/Data).Output()) 7 | 8 | 9 | SELECT events.* 10 | FROM (SELECT * FROM EVENTS) events 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/020_generate_post_except/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "quantity": -1234 4 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/020_generate_post_except/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "quantity": -2345 4 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/020_generate_post_except/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/post_except.sql", 4 | "Args": "-G=post" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/020_generate_post_except/post_except.sql: -------------------------------------------------------------------------------- 1 | /* {"URI": "basic/events-except", "Method": "POST" } */ 2 | 3 | #set($_ = $Events(body/).Cardinality('One').Tag('anonymous:"true"')) 4 | #set($_ = $Events(body/).Output().Tag('anonymous:"true"')) 5 | 6 | 7 | 8 | SELECT events.* EXCEPT NAME 9 | FROM (SELECT * FROM EVENTS) events 10 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/021_generate_post_explicit_columns/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "quantity": -3456 4 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/021_generate_post_explicit_columns/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "quantity": -4567 4 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/021_generate_post_explicit_columns/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/post_explicit.sql", 4 | "Args": "-G=post" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/021_generate_post_explicit_columns/post_explicit.sql: -------------------------------------------------------------------------------- 1 | /* {"URI": "basic/events-explicit", "Method": "POST" } */ 2 | 3 | #set($_ = $Events(body/).Cardinality('One').Tag('anonymous:"true"')) 4 | #set($_ = $Events(body/).Output().Tag('anonymous:"true"')) 5 | 6 | 7 | SELECT events.* 8 | FROM (SELECT ID, QUANTITY FROM EVENTS) events 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/022_generate_post_one_one/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "quantity": -5678, 4 | "eventsPerformance": { 5 | "id": "@exists@", 6 | "price": -6789, 7 | "eventId": "@exists@" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/022_generate_post_one_one/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/post_one_one.sql", 4 | "Args": "-G=post" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/022_generate_post_one_one/post_one_one.sql: -------------------------------------------------------------------------------- 1 | /* {"URI": "basic/events-one-one", "Method": "POST" } */ 2 | 3 | 4 | #set($_ = $Events(body/).Cardinality('One').Tag('anonymous:"true"')) 5 | #set($_ = $Events(body/).Output().Tag('anonymous:"true"')) 6 | 7 | 8 | SELECT EVENTS.*, 9 | EVENTS_PERFORMANCE.* 10 | FROM (SELECT ID, QUANTITY FROM EVENTS) EVENTS 11 | JOIN (SELECT * FROM EVENTS_PERFORMANCE) EVENTS_PERFORMANCE ON EVENTS.ID = EVENTS_PERFORMANCE.EVENT_ID AND 1=1 -------------------------------------------------------------------------------- /e2e/local/regression/cases/023_generate_post_one_many/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "quantity": -7890, 4 | "eventsPerformance": [ 5 | { 6 | "id": "@exists@", 7 | "price": -8901, 8 | "eventId": "@exists@" 9 | }, 10 | { 11 | "id": "@exists@", 12 | "price": -9012, 13 | "eventId": "@exists@" 14 | }, 15 | { 16 | "id": "@exists@", 17 | "price": -10123, 18 | "eventId": "@exists@" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/023_generate_post_one_many/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/post_one_many.sql", 4 | "Args": "-G=post" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/023_generate_post_one_many/post_one_many.sql: -------------------------------------------------------------------------------- 1 | /* {"URI": "basic/events-one-many", "Method": "POST" } */ 2 | 3 | #set($_ = $Events(body/).Cardinality('One').Tag('anonymous:"true"')) 4 | #set($_ = $Events(body/).Output().Tag('anonymous:"true"')) 5 | 6 | 7 | SELECT EVENTS.*, 8 | EVENTS_PERFORMANCE.* 9 | FROM (SELECT ID, QUANTITY FROM EVENTS) EVENTS 10 | JOIN (SELECT * FROM EVENTS_PERFORMANCE) EVENTS_PERFORMANCE ON EVENTS.ID = EVENTS_PERFORMANCE.EVENT_ID -------------------------------------------------------------------------------- /e2e/local/regression/cases/024_validator_codec/Events.go: -------------------------------------------------------------------------------- 1 | package tmp 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type Events struct { 8 | Id int `sqlx:"ID"` 9 | Quantity int `sqlx:"QUANTITY"` 10 | EventsPerformance []*EventsPerformance `typeName:"EventsPerformance" sqlx:"-"` 11 | } 12 | 13 | type EventsPerformance struct { 14 | Id int `sqlx:"ID"` 15 | Price int `sqlx:"PRICE"` 16 | EventId int `sqlx:"-"` 17 | Timestamp time.Time `sqlx:"TIMESTAMP"` 18 | } 19 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/024_validator_codec/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "quantity": 0, 4 | "eventsPerformance": [ 5 | { 6 | "id": "@exists@", 7 | "price": 125, 8 | "eventId": "@exists@" 9 | }, 10 | { 11 | "id": "@exists@", 12 | "price": 250, 13 | "eventId": "@exists@" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/024_validator_codec/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "price can't be negative" 3 | } 4 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/024_validator_codec/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/validator_codec.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/025_structql_velocity/Events.go: -------------------------------------------------------------------------------- 1 | package tmp 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type Events struct { 8 | Id int `sqlx:"ID"` 9 | Quantity int `sqlx:"QUANTITY"` 10 | EventsPerformance []*EventsPerformance `typeName:"EventsPerformance" sqlx:"-"` 11 | } 12 | 13 | type EventsPerformance struct { 14 | Id int `sqlx:"ID"` 15 | Price int `sqlx:"PRICE"` 16 | EventId int `sqlx:"-"` 17 | Timestamp time.Time `sqlx:"TIMESTAMP"` 18 | } 19 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/025_structql_velocity/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "quantity": 0, 4 | "eventsPerformance": [ 5 | { 6 | "id": "@exists@", 7 | "price": 125, 8 | "eventId": "@exists@" 9 | }, 10 | { 11 | "id": "@exists@", 12 | "price": 250, 13 | "eventId": "@exists@" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/025_structql_velocity/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "price can't be negative" 3 | } 4 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/025_structql_velocity/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/structql_velty.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/026_transform_service/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "quantity": 0, 4 | "eventsPerformance": [ 5 | { 6 | "id": "@exists@", 7 | "price": 125, 8 | "eventId": "@exists@" 9 | }, 10 | { 11 | "id": "@exists@", 12 | "price": 250, 13 | "eventId": "@exists@" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/026_transform_service/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "price can't be negative" 3 | } 4 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/026_transform_service/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/transform_service.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/027_generate_put_basic_one/expect/FOOS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ID": 1, 4 | "Name": "changed - 1" 5 | }, 6 | { 7 | "ID": 2, 8 | "Name": "changed - 123.5" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/027_generate_put_basic_one/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1, 3 | "name": "changed - 1" 4 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/027_generate_put_basic_one/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 2, 3 | "name": "changed - 123.5" 4 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/027_generate_put_basic_one/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/put_basic_one.sql", 4 | "Args": "-G=put" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/027_generate_put_basic_one/put_basic_one.sql: -------------------------------------------------------------------------------- 1 | /* { "URI": "basic/foos", "Method": "PUT" } */ 2 | 3 | #set($_ = $Foos(body/).Cardinality('One').Tag('anonymous:"true"')) 4 | #set($_ = $Foos(body/).Output().Tag('anonymous:"true"')) 5 | 6 | 7 | SELECT foos.* 8 | FROM (SELECT * FROM FOOS) foos 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/028_generate_put_basic_many/expect/FOOS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ID": 1, 4 | "Name": "changed - 180" 5 | }, 6 | { 7 | "ID": 2, 8 | "Name": "changed - 250" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/028_generate_put_basic_many/expect_t0.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "changed - 180" 5 | }, 6 | { 7 | "id": 2, 8 | "name": "changed - 250" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/028_generate_put_basic_many/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/put_basic_many.sql", 4 | "Args": "-G=put" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/028_generate_put_basic_many/put_basic_many.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI": "basic/foos-many", "Method": "PUT" 3 | } */ 4 | 5 | #set($_ = $Foos(body/).Cardinality('Many').Tag('anonymous:"true"')) 6 | #set($_ = $Foos(body/).Output().Tag('anonymous:"true"')) 7 | 8 | SELECT foos.* 9 | FROM (SELECT * FROM FOOS) foos 10 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/029_generate_put_one_many/expect/FOOS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ID": 1, 4 | "Name": "changed foo - 250" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/029_generate_put_one_many/expect/FOOS_PERFORMANCE.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ID": 1, 4 | "PERF_NAME": "changed perf - x", 5 | "PERF_QUANTITY": 999, 6 | "FOO_ID": 2 7 | }, 8 | { 9 | "ID": 2, 10 | "PERF_NAME": "changed perf - 2", 11 | "PERF_QUANTITY": 1998, 12 | "FOO_ID": 1 13 | }, 14 | { 15 | "ID": 3, 16 | "PERF_NAME": "changed perf - 3", 17 | "PERF_QUANTITY": 2997, 18 | "FOO_ID": 2 19 | } 20 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/029_generate_put_one_many/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1, 3 | "name": "changed foo - 250", 4 | "foosPerformance": [ 5 | {"@indexBy@": "id"}, 6 | { 7 | "id": 1, 8 | "perfName": "changed perf - 1", 9 | "perfQuantity": 999 10 | }, 11 | { 12 | "id": 2, 13 | "perfName": "changed perf - 2", 14 | "perfQuantity": 1998 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/029_generate_put_one_many/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 2, 3 | "name": "changed foo - 500", 4 | "foosPerformance": [ 5 | {"@indexBy@": "id"}, 6 | { 7 | "id": 1, 8 | "perfName": "changed perf - x", 9 | "perfQuantity": 999, 10 | "fooId": 2 11 | }, 12 | { 13 | "id": 3, 14 | "perfName": "changed perf - 3", 15 | "perfQuantity": 2997, 16 | "fooId": 2 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/029_generate_put_one_many/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/put_one_many.sql", 4 | "Args": "-G=put" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/029_generate_put_one_many/put_one_many.sql: -------------------------------------------------------------------------------- 1 | /* { "URI": "basic/foos-one-many", "Method": "PUT"} */ 2 | 3 | #set($_ = $Foos(body/).Cardinality('One').Tag('anonymous:"true"')) 4 | #set($_ = $Foos(body/).Output().Tag('anonymous:"true"')) 5 | 6 | 7 | SELECT foos.*, 8 | foosPerformance.* 9 | FROM (SELECT * FROM FOOS) foos 10 | JOIN (SELECT * FROM FOOS_PERFORMANCE) foosPerformance on foos.ID = foosPerformance.FOO_ID -------------------------------------------------------------------------------- /e2e/local/regression/cases/030_insert_acl/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/user_acl.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/030_insert_acl/skip.txt: -------------------------------------------------------------------------------- 1 | Deprecated -------------------------------------------------------------------------------- /e2e/local/regression/cases/031_generate_patch_basic_one/expect/FOOS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ID": 1, 4 | "Name": "changed foo - 250" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/031_generate_patch_basic_one/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 4, 3 | "quantity": 2500, 4 | "name": "changed - foo 4" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/031_generate_patch_basic_one/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "@exists@", 3 | "quantity": 1234, 4 | "name": "created" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/031_generate_patch_basic_one/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/patch_basic_one.sql", 4 | "Args": "-G=patch" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/031_generate_patch_basic_one/patch_basic_one.sql: -------------------------------------------------------------------------------- 1 | /* {"URI": "basic/foos", "Method": "PATCH"} */ 2 | 3 | #set($_ = $Foos(body/).Cardinality('One').Tag('anonymous:"true"')) 4 | #set($_ = $Foos(body/).Output().Tag('anonymous:"true"')) 5 | 6 | 7 | 8 | SELECT foos.* 9 | FROM (SELECT * FROM FOOS) foos 10 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/032_generate_patch_basic_many/expect/FOOS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ID": 1, 4 | "Name": "changed foo - 250" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/032_generate_patch_basic_many/expect_t0.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 5, 4 | "name": "changed - foo 5", 5 | "quantity": 5000 6 | }, 7 | { 8 | "id": "@exists@", 9 | "name": "created - foo 5", 10 | "quantity": 10000 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/032_generate_patch_basic_many/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/patch_basic_many.sql", 4 | "Args": "-G=patch" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/032_generate_patch_basic_many/patch_basic_many.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI": "basic/foos-many", "Method": "PATCH" 3 | } */ 4 | 5 | #set($_ = $Foos(body/).Cardinality('Many').Tag('anonymous:"true"')) 6 | #set($_ = $Foos(body/).Output().Tag('anonymous:"true"')) 7 | 8 | 9 | SELECT foos.* 10 | FROM (SELECT * FROM FOOS) foos 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/033_generate_patch_many_many/expect/FOOS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ID": 1, 4 | "Name": "changed foo - 250" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/033_generate_patch_many_many/expect_t0.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 5, 4 | "name": "changed - foo 5", 5 | "quantity": 5000, 6 | "foosPerformance": [ 7 | { 8 | "id": 5, 9 | "perfName": "updated foos perf - 5", 10 | "perfQuantity": -1000, 11 | "fooId": 5 12 | } 13 | ] 14 | }, 15 | { 16 | "id": "@exists@", 17 | "name": "created - foo 6", 18 | "quantity": 9898, 19 | "foosPerformance": [] 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/033_generate_patch_many_many/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/patch_basic_many_many.sql", 4 | "Args": "-G=patch" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/033_generate_patch_many_many/patch_basic_many_many.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI": "basic/foos-many-many", "Method": "PATCH" 3 | } */ 4 | 5 | #set($_ = $Foos(body/).Cardinality('Many').Tag('anonymous:"true"')) 6 | #set($_ = $Foos(body/).Output().Tag('anonymous:"true"')) 7 | 8 | 9 | SELECT foos.*, 10 | foosPerformance.* 11 | FROM (SELECT * FROM FOOS) foos 12 | JOIN (SELECT * FROM FOOS_PERFORMANCE) foosPerformance on foos.ID = foosPerformance.FOO_ID 13 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/034_inserter/expect_t0.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "034_ changed - foo 6", 4 | "quantity": 5000 5 | }, 6 | { 7 | "name": "034_ created - foo 5", 8 | "quantity": 10000 9 | } 10 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/034_inserter/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/inserter.sql", 4 | "Args": "-G=post" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/034_inserter/inserter.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI": "basic/foos-inserter", "Method": "POST" 3 | } */ 4 | 5 | #set($_ = $Foos(body/).Cardinality('Many').Tag('anonymous:"true"')) 6 | #set($_ = $Foos(body/).Output().Tag('anonymous:"true"')) 7 | 8 | 9 | SELECT foos.* 10 | FROM (SELECT * FROM FOOS) foos 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/035_updater/expect_t0.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "@indexBy@": "id" 4 | }, 5 | { 6 | "id": 7, 7 | "name": "035_ changed - foo 7", 8 | "quantity": 123456 9 | }, 10 | { 11 | "id": 8, 12 | "name": "035_ changed - foo 8" 13 | } 14 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/035_updater/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/updater.sql", 4 | "Args": "-G=put --execKind=service" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/035_updater/updater.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI": "basic/foos-updater", "Method": "PUT" 3 | } */ 4 | 5 | #set($_ = $Foos(body/).Cardinality('Many').Tag('anonymous:"true"')) 6 | #set($_ = $Foos(body/).Output().Tag('anonymous:"true"')) 7 | 8 | 9 | SELECT foos.* 10 | FROM (SELECT * FROM FOOS) foos 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/036_differ/foos.go: -------------------------------------------------------------------------------- 1 | package generated 2 | 3 | type Foos struct { 4 | Id int `sqlx:"ID,primaryKey"` 5 | Name *string `sqlx:"NAME" json:",omitempty"` 6 | Quantity *int `sqlx:"QUANTITY" json:",omitempty"` 7 | Has *FoosHas `setMarker:"true" typeName:"FoosHas" json:"-" sqlx:"-"` 8 | } 9 | 10 | type FoosHas struct { 11 | Id bool 12 | Name bool 13 | Quantity bool 14 | } 15 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/036_differ/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/differ.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/036_differ/pre_differ.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI": "basic/foos-differ", "Method": "PATCH" 3 | } */ 4 | 5 | SELECT foos.* /* { "Cardinality": "Many" } */ 6 | FROM (SELECT * FROM FOOS) foos /* { "ExecKind": "service", "FetchRecords": true } */ 7 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/037_plugins/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/plugins.sql", 4 | "Args": "", 5 | "ArgsDebug": "--pluginArgs='-gcflags \"all=-N -l\"' " 6 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/037_plugins/plugins.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"basic/foos-plugin","Method":"POST","ResponseBody":{"From":"Foos"}} */ 2 | 3 | import ( 4 | "regression/cases/037_plugins.FooPlugin" AS "FooPlugin" 5 | ) 6 | 7 | #set($_ = $Foos<[]*FooPlugin>(body/)) 8 | #set($_ = $Foos(body/).Output().Tag('anonymous:"true"')) 9 | 10 | $sequencer.Allocate("FOOS", $Foos, "Id") 11 | #foreach($recFoos in $Unsafe.Foos) 12 | $recFoos.Validate() 13 | $sql.Insert($recFoos, "FOOS"); 14 | #end -------------------------------------------------------------------------------- /e2e/local/regression/cases/037_plugins/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: POST 9 | URL: http://127.0.0.1:8080/v1/api/dev/basic/foos-plugin 10 | JsonBody: 11 | - ID: 9 12 | Name: "" 13 | Quantity: -1 14 | Expect: 15 | Code: 400 16 | JSONBody: 17 | message: quantity can't be negative -------------------------------------------------------------------------------- /e2e/local/regression/cases/038_mysql_boolean/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "@indexBy@": "id" 4 | }, 5 | { 6 | "id": 1, 7 | "userId": 1, 8 | "isEnabled": true, 9 | "isActivated": false 10 | }, 11 | { 12 | "id": 2, 13 | "userId": 2, 14 | "isEnabled": false, 15 | "isActivated": true 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/038_mysql_boolean/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/user_metadata.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/038_mysql_boolean/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/user-metadata 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON($parentPath/expect.json) 13 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/038_mysql_boolean/user_metadata.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"user-metadata"} */ 2 | 3 | #set( $_ = $Fields<[]string>(query/fields).Optional().QuerySelector('user_metadata')) 4 | #set( $_ = $Page(query/page).Optional().QuerySelector('user_metadata')) 5 | 6 | #set( $_ = $UserMetadata(output/view).Embed()) 7 | 8 | 9 | SELECT user_metadata.* 10 | FROM (SELECT * FROM USER_METADATA t ) user_metadata 11 | 12 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/039_generate_post_comprehensive_one/expect_t0.json: -------------------------------------------------------------------------------- 1 | 2 | 3 | { 4 | "status": "error", 5 | "errors": [ 6 | { 7 | "view": "post_comprehensive_one", 8 | "parameter": "Events", 9 | "message": "parameter Events is required" 10 | } 11 | ] 12 | } 13 | 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/039_generate_post_comprehensive_one/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/post_comprehensive_one.sql", 4 | "Args": "-G=post" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/039_generate_post_comprehensive_one/post_comprehensive_one.sql: -------------------------------------------------------------------------------- 1 | /* {"URI": "comprehensive/events-one", "Method": "POST" } */ 2 | 3 | #set($_ = $Events(body/Data).Cardinality('One').Tag('anonymous:"true"')) 4 | #set($_ = $Events(body/Data).Output()) 5 | 6 | 7 | SELECT events.* 8 | FROM (SELECT * FROM EVENTS) events 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/039_generate_post_comprehensive_one/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: POST 9 | URL: http://127.0.0.1:8080/v1/api/dev/comprehensive/events-one 10 | JSONBody: 11 | data: null 12 | 13 | Expect: 14 | Code: 400 15 | JSONBody: $LoadJSON('${parentPath}/expect_t0.json') 16 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/040_parameters_order/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "error", 3 | "errors": [ 4 | { 5 | "view": "parameters_order", 6 | "parameter": "Jwt", 7 | "message": "parameter Jwt is required" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/040_parameters_order/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "error", 3 | "errors": [ 4 | { 5 | "view": "parameters_order", 6 | "parameter": "Authorization", 7 | "message": "parameter Authorization value is required but no data was found" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/040_parameters_order/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/parameters_order.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/041_custom_response/expect_t0.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "CustomError message", 3 | "customField": "Quantity has to be \u003e 0", 4 | "defaultMessageSuccess": "Default message success", 5 | "failureMessageSuccess": "Failure message success" 6 | } 7 | 8 | 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/041_custom_response/expect_t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "defaultMessageSuccess": "Default message success", 4 | "successMessageSuccess": "Success message success", 5 | "data": { 6 | "id": "@exists@", 7 | "name": "41_ valid qunaitity", 8 | "quantity": 12345 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/041_custom_response/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/custom_response.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/042_json_codec/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/json_codec.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/042_json_codec/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/json-codec 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/042_json_codec/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type ( 4 | Foo struct { 5 | Id int 6 | Name string 7 | Price float64 8 | } 9 | 10 | Boo struct { 11 | Id int 12 | UpdatedAt string 13 | CreatedAt string 14 | } 15 | 16 | Bar struct { 17 | Id int 18 | Items []interface{} 19 | } 20 | 21 | Record struct { 22 | Id string 23 | Preferences interface{} 24 | ClassName string 25 | } 26 | ) 27 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/043_json_codec_single/expect.json: -------------------------------------------------------------------------------- 1 | { 2 | "preferences": { 3 | "id": 1, 4 | "name": "Foo", 5 | "price": 125.5 6 | }, 7 | "className": "com.class.abc.Foo" 8 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/043_json_codec_single/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/json_codec_single.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/043_json_codec_single/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/json-codec/1 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/043_json_codec_single/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type ( 4 | Foo struct { 5 | Id int 6 | Name string 7 | Price float64 8 | } 9 | 10 | Boo struct { 11 | Id int 12 | UpdatedAt string 13 | CreatedAt string 14 | } 15 | 16 | Bar struct { 17 | Id int 18 | Items []interface{} 19 | } 20 | 21 | Record struct { 22 | Id string 23 | Preferences interface{} 24 | ClassName string 25 | } 26 | ) 27 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/044_inline_json_codec/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Foo", 5 | "price": 125.5 6 | }, 7 | { 8 | "id": 1, 9 | "updatedAt": "03/16/2022", 10 | "createdAt": "01/16/2022" 11 | }, 12 | { 13 | "id": 1, 14 | "items": [ 15 | 0, 16 | "125", 17 | 250, 18 | "275" 19 | ] 20 | } 21 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/044_inline_json_codec/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/inlinejson_codec.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/044_inline_json_codec/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/inlinejson-codec 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/044_inline_json_codec/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type ( 4 | Foo struct { 5 | Id int 6 | Name string 7 | Price float64 8 | } 9 | 10 | Boo struct { 11 | Id int 12 | UpdatedAt string 13 | CreatedAt string 14 | } 15 | 16 | Bar struct { 17 | Id int 18 | Items []interface{} 19 | } 20 | 21 | Record struct { 22 | Id string 23 | Preferences interface{} `jsonx:",inline"` 24 | ClassName string 25 | } 26 | ) 27 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/045_raw_json/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": 1, 4 | "Name": "Foo", 5 | "Price": 125.5 6 | }, 7 | { 8 | "Id": 1, 9 | "UpdatedAt": "03/16/2022", 10 | "CreatedAt": "01/16/2022" 11 | }, 12 | { 13 | "Id": 1, 14 | "Items": [ 15 | 0, 16 | "125", 17 | 250, 18 | "275" 19 | ] 20 | } 21 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/045_raw_json/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/raw_json.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/045_raw_json/raw_json.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"raw_json"} */ 2 | 3 | import ( 4 | "regression/cases/045_raw_json.Record" 5 | ) 6 | 7 | #set( $_ = $Data(output/view).Embed()) 8 | 9 | 10 | SELECT main.*, 11 | cast(main AS Record) 12 | FROM ( 13 | SELECT 14 | ID as Id, 15 | OBJECT AS Preferences, 16 | CLASS_NAME as ClassName 17 | FROM OBJECTS 18 | WHERE ID != 999 19 | ) main -------------------------------------------------------------------------------- /e2e/local/regression/cases/045_raw_json/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/raw_json 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/045_raw_json/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "encoding/json" 4 | 5 | type Record struct { 6 | Id string 7 | Preferences *json.RawMessage `jsonx:",inline"` 8 | ClassName string 9 | } 10 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/046_raw_json_expr/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": 1, 4 | "Name": "Foo", 5 | "Price": 125.5 6 | }, 7 | { 8 | "Id": 1, 9 | "UpdatedAt": "03/16/2022", 10 | "CreatedAt": "01/16/2022" 11 | }, 12 | { 13 | "Id": 1, 14 | "Items": [ 15 | 0, 16 | "125", 17 | 250, 18 | "275" 19 | ] 20 | } 21 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/046_raw_json_expr/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/raw_json_tag.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/046_raw_json_expr/raw_json_tag.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"raw_json_tag"} */ 2 | 3 | #set( $_ = $Data(output/view).Embed()) 4 | 5 | 6 | SELECT main.* 7 | FROM ( 8 | SELECT 9 | ID as Id, 10 | OBJECT AS Preferences /* {"DataType": "json.RawMessage", "Tag":"jsonx:\",inline\""} */, 11 | CLASS_NAME as ClassName 12 | FROM OBJECTS 13 | WHERE ID != 999 14 | ) main -------------------------------------------------------------------------------- /e2e/local/regression/cases/046_raw_json_expr/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/raw_json_tag 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/047_raw_json_tag/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/raw_json_expr.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/047_raw_json_tag/raw_json_expr.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"raw_json_expr"} */ 2 | 3 | #set( $_ = $Data(output/view).Embed()) 4 | 5 | 6 | SELECT main.*, 7 | cast(main.Name AS string) 8 | FROM ( 9 | SELECT 10 | ID as Id, 11 | OBJECT AS Preferences /* {"DataType": "json.RawMessage"} */, 12 | (OBJECT->'$.Name') AS Name /* {"DataType":"string"} */, 13 | CLASS_NAME as ClassName 14 | FROM OBJECTS 15 | WHERE ID != 999 16 | ) main -------------------------------------------------------------------------------- /e2e/local/regression/cases/047_raw_json_tag/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/raw_json_expr 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/048_json_persist_with_type/expect.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 999, 3 | "object": { 4 | "id": 1, 5 | "name": "Foo", 6 | "price": 125.5 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/048_json_persist_with_type/expect2.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "error", 3 | "errors": [ 4 | { 5 | "view": "custom_unmarshall_velty", 6 | "parameter": "Preference", 7 | "message": "json: cannot unmarshal array into Go value of type struct { Id int; Name string; Price float64 }" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/048_json_persist_with_type/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/custom_unmarshall_velty.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/049_oauth_hmac/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 2, 4 | "name": "Vendor 2", 5 | "firstName": "Developer", 6 | "products": [ 7 | { 8 | "@indexBy@": "id" 9 | }, 10 | { 11 | "id": 3, 12 | "name": "V2 Product 1", 13 | "userCreated": 2 14 | }, 15 | { 16 | "id": 4, 17 | "name": "V2 Product 2", 18 | "userCreated": 2 19 | }, 20 | { 21 | "id": 5, 22 | "name": "V2 Product 3", 23 | "userCreated": 2 24 | } 25 | ] 26 | } 27 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/049_oauth_hmac/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendor_hauth.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/050_redirect/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "@indexBy@": "id" 4 | }, 5 | { 6 | "id": 1, 7 | "name": "Vendor 1", 8 | "products": [ 9 | { 10 | "@indexBy@": "id" 11 | }, 12 | { 13 | "id": 1, 14 | "name": "V1 Product 1", 15 | "userCreated": 1 16 | }, 17 | { 18 | "id": 2, 19 | "name": "V1 Product 2", 20 | "userCreated": 1 21 | } 22 | ] 23 | }, 24 | { 25 | "id": 2, 26 | "name": "Vendor 2" 27 | }, 28 | { 29 | "id": 3, 30 | "name": "Vendor 3" 31 | } 32 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/050_redirect/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/redirect.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/050_redirect/redirect.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"composition/xxx", 2 | "Method":"GET", 3 | "Type":"handler.ProxyProvider", 4 | "HandlerArgs":["GET", "/v1/api/dev/vendors"] 5 | } */ 6 | 7 | #set( $_ = $Fields<[]string>(query/fields).Value('id,name')) 8 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/050_redirect/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/composition/xxx 10 | Expect: 11 | Code: 200 12 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/051_redirect_vendors/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "@indexBy@": "id" 4 | }, 5 | { 6 | "id": 1, 7 | "name": "Vendor 1", 8 | "products": [ 9 | { 10 | "@indexBy@": "id" 11 | }, 12 | { 13 | "id": 1, 14 | "name": "V1 Product 1", 15 | "userCreated": 1 16 | }, 17 | { 18 | "id": 2, 19 | "name": "V1 Product 2", 20 | "userCreated": 1 21 | } 22 | ] 23 | }, 24 | { 25 | "id": 2, 26 | "name": "Vendor 2" 27 | }, 28 | { 29 | "id": 3, 30 | "name": "Vendor 3" 31 | } 32 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/051_redirect_vendors/expect2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "accountId": 100, 4 | "id": 1, 5 | "name": "Vendor 1", 6 | "products": [ 7 | { 8 | "@indexBy@": "id" 9 | }, 10 | { 11 | "id": 1, 12 | "name": "V1 Product 1" 13 | }, 14 | { 15 | "id": 2, 16 | "name": "V1 Product 2" 17 | } 18 | ], 19 | "userCreated": 1, 20 | "userUpdated": 0 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/051_redirect_vendors/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/redirect_vendor_list.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/051_redirect_vendors/redirect_vendor_details.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"red_vendors/{vendorID}"} */ 2 | SELECT vendor.*, 3 | products.* EXCEPT VENDOR_ID 4 | FROM (SELECT * FROM VENDOR t WHERE t.ID = $vendorID ) vendor 5 | JOIN (SELECT * FROM PRODUCT t) products ON products.VENDOR_ID = vendor.ID -------------------------------------------------------------------------------- /e2e/local/regression/cases/051_redirect_vendors/redirect_vendor_list.sql: -------------------------------------------------------------------------------- 1 | /* { "URI": "red_vendors" } */ 2 | SELECT vendor.*, 3 | products.* EXCEPT VENDOR_ID 4 | FROM (SELECT * FROM VENDOR t ) vendor 5 | JOIN (SELECT * FROM PRODUCT t) products ON products.VENDOR_ID = vendor.ID 6 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/051_redirect_vendors/router.vm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | { 4 | "URL": "/custom-redirect/", 5 | "TemplateURL": "./router.vm", 6 | "Routes": [ 7 | {"SourceURL": "./redirect_vendor_details.sql"}, 8 | {"SourceURL": "./redirect_vendor_list.sql"} 9 | ] 10 | } 11 | 12 | */ 13 | 14 | #if(($request.QueryParam("vendorID") != "")) 15 | ${router.RedirectTo("/vendors/" + $request.QueryParam("vendorID"))} 16 | #end -------------------------------------------------------------------------------- /e2e/local/regression/cases/051_redirect_vendors/skip.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/e2e/local/regression/cases/051_redirect_vendors/skip.txt -------------------------------------------------------------------------------- /e2e/local/regression/cases/051_redirect_vendors/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/custom-redirect/vendors 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | 14 | - Method: GET 15 | URL: http://127.0.0.1:8080/v1/api/dev/custom-redirect/vendors?vendorID=1 16 | Expect: 17 | Code: 200 18 | JSONBody: $LoadJSON('${parentPath}/expect2.json') 19 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/052_json_persist/expect.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 999, 3 | "object": { 4 | "id": 1, 5 | "name": "Foo", 6 | "price": 125.5, 7 | "info": { 8 | "k1": 2, 9 | "K2": 3 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/052_json_persist/expect2.json: -------------------------------------------------------------------------------- 1 | { 2 | "Status": "error", 3 | "Errors": [ 4 | { 5 | "View": "custom_unmarshall_velty", 6 | "Param": "Preference", 7 | "Message": "json: cannot unmarshal array into Go value of type struct { Id int; Name string; Price float64 }" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/052_json_persist/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/json_persist.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/052_json_persist/json_persist.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"json-persist","Method":"PUT"} */ 2 | 3 | import ( 4 | "regression/cases/052_json_persist.Preference" 5 | ) 6 | 7 | #set( $_ = $Preference<*Preference>(body/)) 8 | #set( $_ = $Preference<*Preference>(body/).Tag('anonymous:"true"').Output()) 9 | 10 | 11 | UPDATE OBJECTS SET 12 | OBJECT = $json.Marshal($Unsafe.Preference.Object) 13 | WHERE ID = $Preference.Id 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/052_json_persist/preference.go: -------------------------------------------------------------------------------- 1 | package _48_custom_unmarshall_velty 2 | 3 | var PackageName = "preference" 4 | 5 | type Preference struct { 6 | Id int `sqlx:"ID,autoincrement,primaryKey,required"` 7 | Object *Foo `sqlx:"OBJECT" json:",omitempty"` 8 | Has *PreferenceHas `setMarker:"true" typeName:"PreferenceHas" json:"-" ` 9 | } 10 | 11 | type PreferenceHas struct { 12 | Id bool 13 | Object bool 14 | } 15 | 16 | type Foo struct { 17 | Id int 18 | Name string 19 | Price float64 20 | Info map[string]int 21 | } 22 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/052_json_persist/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: PUT 9 | URL: http://127.0.0.1:8080/v1/api/dev/json-persist 10 | JSONBody: 11 | Id: 999 12 | Object: 13 | Id: 1 14 | Name: Foo 15 | Price: 125.5 16 | Info: 17 | k1: 2 18 | K2: 3 19 | Expect: 20 | Code: 200 21 | JSONBody: $LoadJSON('${parentPath}/expect.json') 22 | 23 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/053_dql_persist/expect.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 999, 3 | "object": { 4 | "id": 1, 5 | "name": "Foo", 6 | "price": 125.5, 7 | "info": { 8 | "k1": 2, 9 | "K2": 3 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/053_dql_persist/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/dql_persist.dql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/053_dql_persist/preference.go: -------------------------------------------------------------------------------- 1 | package _48_custom_unmarshall_velty 2 | 3 | var PackageName = "preference" 4 | 5 | type Preference struct { 6 | Id int `sqlx:"ID,autoincrement,primaryKey,required"` 7 | Object *Foo `sqlx:"OBJECT" json:",omitempty" ` 8 | Has *PreferenceHas `setMarker:"true" typeName:"PreferenceHas" json:"-" sqlx:"-"` 9 | } 10 | 11 | type PreferenceHas struct { 12 | Id bool 13 | Object bool 14 | } 15 | 16 | type Foo struct { 17 | Id int 18 | Name string 19 | Price float64 20 | Info map[string]int 21 | } 22 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/054_persist_inlined_json/expect.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 999, 3 | "object": { 4 | "id": 1, 5 | "name": "Foo", 6 | "price": 125.5, 7 | "info": { 8 | "k1": 2, 9 | "K2": 3 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/054_persist_inlined_json/expect2.json: -------------------------------------------------------------------------------- 1 | { 2 | "Status": "error", 3 | "Errors": [ 4 | { 5 | "View": "custom_unmarshall_velty", 6 | "Param": "Preference", 7 | "Message": "json: cannot unmarshal array into Go value of type struct { Id int; Name string; Price float64 }" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/054_persist_inlined_json/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/dql_persist_inlined.dql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/054_persist_inlined_json/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: PUT 9 | URL: http://127.0.0.1:8080/v1/api/dev/dql-persist-inlined 10 | JSONBody: 11 | Id: 999 12 | Object: 13 | Id: 1 14 | Name: Foo 15 | Price: 125.5 16 | Info: 17 | k1: 2 18 | K2: 3 19 | Expect: 20 | Code: 200 21 | JSONBody: $LoadJSON('${parentPath}/expect.json') 22 | 23 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/055_variables/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key1": "setting1 - VENDOR", 4 | "key2": "setting2 - PRODUCT", 5 | "key3": true 6 | } 7 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/055_variables/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vars.sql", 4 | "Args": "-x='ws'" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/055_variables/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "Vendor": "VENDOR", 3 | "Product": "PRODUCT", 4 | "Var1": "setting1", 5 | "Var2": "setting2", 6 | "Var3": true, 7 | "DummyTable": "DUAL" 8 | } 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/055_variables/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/ws/vars/ 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/055_variables/vars.sql: -------------------------------------------------------------------------------- 1 | /* 2 | { 3 | "URI": "vars/", 4 | "ConstURL": "./properties.json" 5 | } 6 | */ 7 | 8 | #set( $_ = $Data(output/view).Embed()) 9 | 10 | 11 | SELECT main.* 12 | FROM ( 13 | SELECT 14 | '$Var1 - $Vendor' AS Key1, 15 | '$Var2 - $Product' AS Key2, 16 | $Var3 as Key3 /* { "DataType": "bool" } */ 17 | FROM $DummyTable 18 | ) main 19 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/056_custom_patch/expect_t0.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "id": 10, 3 | "name": "changed - foo 10", 4 | "quantity": 5000 5 | }] -------------------------------------------------------------------------------- /e2e/local/regression/cases/056_custom_patch/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/patch_custom.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/056_custom_patch/pre_gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/pre_patch_custom.sql", 4 | "Args": "-G=patch --loadSQL" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/056_custom_patch/pre_patch_custom.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI": "basic/patch-custom", "Method": "PATCH" 3 | } */ 4 | 5 | #set($_ = $Foos<*>(body/).Tag('anonymous:"true"')) 6 | #set($_ = $Foos<*>(body/).Output().Tag('anonymous:"true"')) 7 | 8 | 9 | SELECT foos.*, 10 | foosPerformance.* 11 | FROM (SELECT * FROM FOOS) foos 12 | JOIN (SELECT * FROM FOOS_PERFORMANCE) foosPerformance on foos.ID = foosPerformance.FOO_ID 13 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/057_patch_types/expect_t0.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 10, 4 | "name": "changed - foo 10", 5 | "quantity": 5000 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/057_patch_types/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/pre_patch_types.sql", 4 | "Args": "-G=patch" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/057_patch_types/pre_gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/pre_patch_custom.sql", 4 | "Args": "-G=patch --loadSQL" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/057_patch_types/pre_patch_types.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI": "basic/patch-types", "Method": "PATCH" 3 | } */ 4 | 5 | #set($_ = $Foos(body/).Cardinality('Many').Tag('anonymous:"true"')) 6 | #set($_ = $Foos(body/).Output().Cardinality('Many').Tag('anonymous:"true"')) 7 | 8 | 9 | SELECT foos.*, 10 | foosPerformance.* 11 | FROM (SELECT * FROM FOOS) foos 12 | JOIN (SELECT * FROM FOOS_PERFORMANCE) foosPerformance on foos.ID = foosPerformance.FOO_ID 13 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/058_tabjson_one_to_many/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/tabular_vendor_list.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/058_tabjson_one_to_many/tabular_vendor_list.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"tabular/basic/vendors/", "DataFormat":"tabular", "TabularJSON":{"FloatPrecision":"20"}} */ 2 | 3 | #set( $_ = $Data(output/view).Embed()) 4 | 5 | SELECT vendor.* EXCEPT CREATED,UPDATED, 6 | products.* EXCEPT VENDOR_ID,CREATED,UPDATED 7 | FROM (SELECT * FROM VENDOR t ) vendor 8 | LEFT JOIN (SELECT * FROM PRODUCT t) products ON products.VENDOR_ID = vendor.ID 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/058_tabjson_one_to_many/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/tabular/basic/vendors/ 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | 14 | 15 | - Method: GET 16 | URL: http://127.0.0.1:8080/v1/api/meta/struct/dev/tabular/basic/vendors/ 17 | Expect: 18 | Code: 200 19 | Body: $Cat('${parentPath}/expect_2.txt') 20 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/059_tabjson_basic/bar_list.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"basic/bars/", "DataFormat":"tabular", "TabularJSON":{"FloatPrecision":"8"}} */ 2 | 3 | #set( $_ = $Data(output/view).Embed()) 4 | 5 | SELECT bar.* 6 | FROM (SELECT * FROM BAR t ) bar 7 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/059_tabjson_basic/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | "Id", 4 | "Name", 5 | "Price", 6 | "Tax" 7 | ], 8 | [ 9 | 1, 10 | "BAR - 1", 11 | 1.12345678, 12 | 0.01123457 13 | ], 14 | [ 15 | 2, 16 | "BAR - 2", 17 | 2.23456780, 18 | 0.02234568 19 | ], 20 | [ 21 | 3, 22 | "BAR - 3", 23 | 3.34567801, 24 | 0.03345678 25 | ] 26 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/059_tabjson_basic/expect_2.txt: -------------------------------------------------------------------------------- 1 | package generated 2 | 3 | type GeneratedStruct struct { 4 | Id int `sqlx:"ID" velty:"names=ID|Id"` 5 | Name *string `sqlx:"NAME" velty:"names=NAME|Name"` 6 | Price *float64 `sqlx:"PRICE" velty:"names=PRICE|Price"` 7 | Tax *float64 `sqlx:"TAX" velty:"names=TAX|Tax"` 8 | } 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/059_tabjson_basic/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/bar_list.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/059_tabjson_basic/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/basic/bars/ 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | 14 | 15 | - Method: GET 16 | URL: http://127.0.0.1:8080/v1/api/meta/struct/dev/basic/bars/ 17 | Expect: 18 | Code: 200 19 | Body: $Cat('${parentPath}/expect_2.txt') 20 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/060_tabjson_comprehensive/bar_comprehensive_list.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"comprehensive/bars/", "DataFormat":"tabular", "TabularJSON":{"FloatPrecision":"-1"}} */ 2 | 3 | 4 | #set( $_ = $Data(output/view).Cardinality('Many')) 5 | #set($_ = $Status(output/status)) 6 | 7 | SELECT bar.* 8 | FROM (SELECT * FROM BAR t ) bar 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/060_tabjson_comprehensive/expect.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "data": [ 4 | [ 5 | "Id", 6 | "Name", 7 | "Price", 8 | "Tax" 9 | ], 10 | [ 11 | 1, 12 | "BAR - 1", 13 | 1.1234567801234567, 14 | 0.0112345675 15 | ], 16 | [ 17 | 2, 18 | "BAR - 2", 19 | 2.2345678012345678, 20 | 0.022345679 21 | ], 22 | [ 23 | 3, 24 | "BAR - 3", 25 | 3.345678012345678, 26 | 0.03345678 27 | ] 28 | ] 29 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/060_tabjson_comprehensive/expect_2.txt: -------------------------------------------------------------------------------- 1 | package generated 2 | 3 | type GeneratedStruct struct { 4 | Id int `sqlx:"ID" velty:"names=ID|Id"` 5 | Name *string `sqlx:"NAME" velty:"names=NAME|Name"` 6 | Price *float64 `sqlx:"PRICE" velty:"names=PRICE|Price"` 7 | Tax *float64 `sqlx:"TAX" velty:"names=TAX|Tax"` 8 | } 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/060_tabjson_comprehensive/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/bar_comprehensive_list.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/060_tabjson_comprehensive/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/comprehensive/bars/ 10 | Expect: 11 | Code: 200 12 | JSONBody: $LoadJSON('${parentPath}/expect.json') 13 | 14 | 15 | - Method: GET 16 | URL: http://127.0.0.1:8080/v1/api/meta/struct/dev/comprehensive/bars/ 17 | Expect: 18 | Code: 200 19 | Body: $Cat('${parentPath}/expect_2.txt') 20 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/061_read_async/expect_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "job": { 3 | "jobType": "Reader", 4 | "mainView": "vendor", 5 | "method": "GET", 6 | "matchKey": "vendor/jobid=123", 7 | "uri": "/v1/api/dev/async/vendor/2", 8 | "userEmail": "dev@viantint.com", 9 | "userId": "2" 10 | }, 11 | 12 | "status": "ok" 13 | } 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/061_read_async/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendor_auth_async.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/061_read_async/root.go: -------------------------------------------------------------------------------- 1 | package _61_read_async 2 | 3 | import "github.com/viant/xdatly/handler/response" 4 | 5 | type Detail struct { 6 | Result interface{} `parameter:"kind=output,in=data"` 7 | Status response.Status `parameter:"kind=output,in=status"` 8 | Job interface{} `parameter:"kind=output,in=job"` 9 | } 10 | 11 | type Root struct { 12 | AllDone bool `parameter:"kind=output,in=async.done" json:",omitempty"` 13 | Detail Detail `parameter:"kind=group" json:",omitempty"` 14 | } 15 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/062_predicates/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Vendor 1" 5 | } 6 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/062_predicates/expect2.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /e2e/local/regression/cases/062_predicates/expect3.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 2, 4 | "name": "Vendor 2", 5 | "userUpdated": 0 6 | } 7 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/062_predicates/expect4.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Vendor 1", 5 | "accountId": 100 6 | }, 7 | { 8 | "id": 2, 9 | "name": "Vendor 2", 10 | "accountId": 101 11 | }, 12 | { 13 | "id": 3, 14 | "name": "Vendor 3", 15 | "accountId": 100 16 | } 17 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/062_predicates/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendors_predicate.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/063_external_parameters/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Vendor 1" 5 | } 6 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/063_external_parameters/expect2.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /e2e/local/regression/cases/063_external_parameters/expect3.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 2, 4 | "name": "Vendor 2", 5 | "userUpdated": 0 6 | } 7 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/063_external_parameters/expect4.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Vendor 1", 5 | "accountId": 100 6 | }, 7 | { 8 | "id": 2, 9 | "name": "Vendor 2", 10 | "accountId": 101 11 | }, 12 | { 13 | "id": 3, 14 | "name": "Vendor 3", 15 | "accountId": 100 16 | } 17 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/063_external_parameters/external_parameters.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI":"external-parameters", 3 | "Method": "GET", 4 | "Include": ["./parameters.sql"] 5 | } */ 6 | 7 | 8 | #set( $_ = $Data(output/view).Embed()) 9 | 10 | 11 | SELECT vendor.* 12 | FROM (SELECT * 13 | FROM VENDOR t 14 | WHERE 1 = 1 ${predicate.Builder().CombineOr( 15 | $predicate.FilterGroup(0, "AND"), 16 | $predicate.FilterGroup(1, "OR" ) 17 | ).Build("AND")} 18 | ) vendor -------------------------------------------------------------------------------- /e2e/local/regression/cases/063_external_parameters/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/external_parameters.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/063_external_parameters/parameters.sql: -------------------------------------------------------------------------------- 1 | #set($_ = $ID(query/ID).WithPredicate(0, "equal", "t", "ID").Optional()) 2 | #set($_ = $UserCreated(query/UserCreated).WithPredicate(0, "equal", "t", "USER_CREATED").Optional()) 3 | #set($_ = $Name(query/Name).WithPredicate(1, "equal", "t", "NAME").Optional()) 4 | #set($_ = $AccountID(query/AccountID).WithPredicate(1, "equal", "t", "ACCOUNT_ID").Optional()) 5 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/064_params_group/expect1.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"@indexBy@": "id"}, 3 | { 4 | "id": 1, 5 | "name": "BAR - 1", 6 | "price": 1.1234567801234567, 7 | "tax": 0.0112345675 8 | }, 9 | { 10 | "id": 2, 11 | "name": "BAR - 2", 12 | "price": 2.2345678012345678, 13 | "tax": 0.022345679 14 | }, 15 | { 16 | "id": 3, 17 | "name": "BAR - 3", 18 | "price": 3.345678012345678, 19 | "tax": 0.03345678 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/064_params_group/expect2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 3, 4 | "name": "BAR - 3", 5 | "price": 3.345678012345678, 6 | "tax": 0.03345678 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/064_params_group/expect3.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/064_params_group/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/params_group.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/065_encode_struct/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 2, 4 | "name": "Vendor 2", 5 | "accountId": 101, 6 | "userCreated": 2 7 | } 8 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/065_encode_struct/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/encode_struct.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/065_encode_struct/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | runTests: 5 | action: http/runner:send 6 | requests: 7 | - Method: GET 8 | URL: 'http://127.0.0.1:8080/v1/api/dev/vendors-check?ids=2/101/2,2/101/2' 9 | Expect: 10 | JSONBody: $LoadJSON('${parentPath}/expect.json') 11 | 12 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/065_encode_struct/vendor.go: -------------------------------------------------------------------------------- 1 | package encode_struct 2 | 3 | type VendorIds struct { 4 | ID int `sqlx:"column=ID"` 5 | AccountID int `sqlx:"column=ACCOUNT_ID"` 6 | UserCreated int `sqlx:"column=USER_CREATED"` 7 | } 8 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/066_xls_output/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/vendor_xls.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/066_xls_output/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/vendors/xls/ 10 | Expect: 11 | Code: 200 12 | 13 | 14 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/066_xls_output/vendor_xls.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"vendors/xls/", "DataFormat":"xls"} */ 2 | 3 | #set( $_ = $Data(output/view).Embed()) 4 | 5 | 6 | SELECT vendor.*, 7 | products.* EXCEPT VENDOR_ID 8 | FROM (SELECT * FROM VENDOR t ) vendor 9 | JOIN (SELECT * FROM PRODUCT t) products ON products.VENDOR_ID = vendor.ID 10 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/067_xml_basic/expect.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1 5 | BAR - 1 6 | 1.12345678 7 | 0.01123457 8 | 9 | 10 | 2 11 | BAR - 2 12 | 2.23456780 13 | 0.02234568 14 | 15 | 16 | 3 17 | BAR - 3 18 | 3.34567801 19 | 0.03345678 20 | 21 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/067_xml_basic/expect_2.txt: -------------------------------------------------------------------------------- 1 | package generated 2 | 3 | type GeneratedStruct struct { 4 | Id int `sqlx:"ID" velty:"names=ID|Id"` 5 | Name *string `sqlx:"NAME" velty:"names=NAME|Name"` 6 | Price *float64 `sqlx:"PRICE" velty:"names=PRICE|Price"` 7 | Tax *float64 `sqlx:"TAX" velty:"names=TAX|Tax"` 8 | } 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/067_xml_basic/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/xml_bar_list.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/067_xml_basic/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/xml/basic/bars/ 10 | Expect: 11 | Code: 200 12 | Body: $Cat('${parentPath}/expect.xml') 13 | 14 | 15 | - Method: GET 16 | URL: http://127.0.0.1:8080/v1/api/meta/struct/dev/xml/basic/bars/ 17 | Expect: 18 | Code: 200 19 | Body: $Cat('${parentPath}/expect_2.txt') 20 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/067_xml_basic/xml_bar_list.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"xml/basic/bars/", "DataFormat":"xml", "XML":{"FloatPrecision":"8"}} */ 2 | 3 | 4 | #set( $_ = $Data(output/view).Embed()) 5 | 6 | 7 | SELECT bar.* 8 | FROM (SELECT * FROM BAR t ) bar 9 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/068_xml_one_to_many/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/xml_tabular_vendor_list.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/068_xml_one_to_many/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | 5 | test: 6 | action: http/runner:send 7 | requests: 8 | - Method: GET 9 | URL: http://127.0.0.1:8080/v1/api/dev/xml/basic/vendors/ 10 | Expect: 11 | Code: 200 12 | Body: $Cat('${parentPath}/expect.xml') 13 | 14 | 15 | - Method: GET 16 | URL: http://127.0.0.1:8080/v1/api/meta/struct/dev/xml/basic/vendors/ 17 | Expect: 18 | Code: 200 19 | Body: $Cat('${parentPath}/expect_2.txt') 20 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/068_xml_one_to_many/xml_tabular_vendor_list.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"xml/basic/vendors/", "DataFormat":"xml", "XML":{"FloatPrecision":"20"}} */ 2 | 3 | #set( $_ = $Data(output/view).Embed()) 4 | 5 | 6 | SELECT vendor.* EXCEPT CREATED,UPDATED, 7 | products.* EXCEPT VENDOR_ID,CREATED,UPDATED 8 | FROM (SELECT * FROM VENDOR t ORDER BY ID) vendor 9 | LEFT JOIN (SELECT * FROM PRODUCT t ORDER BY ID) products ON products.VENDOR_ID = vendor.ID 10 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/069_encode_struct_pkg/expect.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 2, 4 | "name": "Vendor 2", 5 | "accountId": 101, 6 | "userCreated": 2 7 | } 8 | ] -------------------------------------------------------------------------------- /e2e/local/regression/cases/069_encode_struct_pkg/gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "$tagId", 3 | "URL": "$path/encode_struct_pkg.sql", 4 | "Args": "" 5 | } -------------------------------------------------------------------------------- /e2e/local/regression/cases/069_encode_struct_pkg/test.yaml: -------------------------------------------------------------------------------- 1 | init: 2 | parentPath: $parent.path 3 | pipeline: 4 | runTests: 5 | action: http/runner:send 6 | requests: 7 | - Method: GET 8 | URL: 'http://127.0.0.1:8080/v1/api/dev/vendors-check-pkg?ids=2/101/2,2/101/2' 9 | Expect: 10 | JSONBody: $LoadJSON('${parentPath}/expect.json') 11 | 12 | -------------------------------------------------------------------------------- /e2e/local/regression/cases/069_encode_struct_pkg/vendor.go: -------------------------------------------------------------------------------- 1 | package encode_struct_pkg 2 | 3 | type VendorIds struct { 4 | ID int `sqlx:"column=ID"` 5 | AccountID int `sqlx:"column=ACCOUNT_ID"` 6 | UserCreated int `sqlx:"column=USER_CREATED"` 7 | } 8 | -------------------------------------------------------------------------------- /e2e/local/regression/db.yaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | pipeline: 4 | register: 5 | action: dsunit:register 6 | datastore: dev 7 | recreate: false 8 | config: 9 | driverName: mysql 10 | descriptor: '[username]:[password]@tcp(${dbIP.mysql}:3306)/[dbname]?parseTime=true' 11 | credentials: $mysqlCredentials 12 | -------------------------------------------------------------------------------- /e2e/local/regression/default/expec.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /e2e/local/regression/partial_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "APIKeys": [ 3 | { 4 | "URI": "/v1/api/ws/secured", 5 | "Value": "changeme", 6 | "Header": "App-Secret-Id", 7 | "Secret": null 8 | }, 9 | { 10 | "URI": "/v1/api/dev/secured", 11 | "Value": "changeme", 12 | "Header": "App-Secret-Id", 13 | "Secret": null 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /e2e/local/validator/src/go.mod: -------------------------------------------------------------------------------- 1 | module validator 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /gateway/doc.go: -------------------------------------------------------------------------------- 1 | // Package gateway defines gateway service 2 | package gateway 3 | -------------------------------------------------------------------------------- /gateway/example/README.md: -------------------------------------------------------------------------------- 1 | ## Example workflow 2 | 3 | 4 | ```bash 5 | endly deploy authWith=$GCP_PROJECT (i.e viant-e2e) 6 | ``` 7 | -------------------------------------------------------------------------------- /gateway/example/routes/test/dual.yaml: -------------------------------------------------------------------------------- 1 | Routes: 2 | - URI: "/v1/api/test/dual" 3 | Method: GET 4 | View: 5 | Ref: dual 6 | 7 | Resource: 8 | Views: 9 | - Name: dual 10 | Connector: 11 | Ref: bq 12 | Table: dual 13 | 14 | Connectors: 15 | - Name: bq 16 | Driver: bigquery 17 | DSN: bigquery://${projectID}/test -------------------------------------------------------------------------------- /gateway/route_status.go: -------------------------------------------------------------------------------- 1 | package gateway 2 | 3 | import ( 4 | "context" 5 | "github.com/viant/datly/repository/contract" 6 | "net/http" 7 | ) 8 | 9 | func (r *Router) NewStatusRoute() *Route { 10 | return &Route{ 11 | Path: contract.NewPath(http.MethodGet, r.config.Meta.StatusURI), 12 | Handler: func(ctx context.Context, writer http.ResponseWriter, req *http.Request) { 13 | r.statusHandler.ServeHTTP(writer, req) 14 | }, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /gateway/router/marshal/init.go: -------------------------------------------------------------------------------- 1 | package marshal 2 | 3 | import ( 4 | "github.com/viant/datly/view/keywords" 5 | "reflect" 6 | ) 7 | 8 | var ctxType = reflect.TypeOf(CustomContext{}) 9 | 10 | func init() { 11 | keywords.RegisterType("Marshal", ctxType) 12 | } 13 | -------------------------------------------------------------------------------- /gateway/router/marshal/json/field.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import "reflect" 4 | 5 | type groupedFields struct { 6 | inlinable []reflect.StructField 7 | presenceFields []reflect.StructField 8 | regularFields []reflect.StructField 9 | owner reflect.Type 10 | } 11 | -------------------------------------------------------------------------------- /gateway/router/marshal/json/marshallable.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | type UnmarshalerInto interface { 6 | UnmarshalJSONWithOptions(dst interface{}, decoder *gojay.Decoder, options ...interface{}) error 7 | } 8 | -------------------------------------------------------------------------------- /gateway/router/marshal/json/marshaller.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | "github.com/francoispqt/gojay" 5 | "unsafe" 6 | ) 7 | 8 | type marshaler interface { 9 | MarshallObject(ptr unsafe.Pointer, session *MarshallSession) error 10 | UnmarshallObject(pointer unsafe.Pointer, decoder *gojay.Decoder, auxiliaryDecoder *gojay.Decoder, session *UnmarshalSession) error 11 | } 12 | -------------------------------------------------------------------------------- /gateway/router/marshal/state.go: -------------------------------------------------------------------------------- 1 | package marshal 2 | 3 | import ( 4 | "github.com/viant/datly/service/executor/expand" 5 | ) 6 | 7 | type State struct { 8 | Ctx CustomContext 9 | ExpandState *expand.State 10 | } 11 | -------------------------------------------------------------------------------- /gateway/router/marshal/tabjson/tags.go: -------------------------------------------------------------------------------- 1 | package tabjson 2 | 3 | const ( 4 | TagName = "csvName" 5 | ) 6 | -------------------------------------------------------------------------------- /gateway/router/metrics.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/viant/xdatly/handler/response" 5 | ) 6 | 7 | type Metrics struct { 8 | URI string 9 | Metrics []*response.Metric 10 | } 11 | 12 | func NewMetrics(URI string, metrics []*response.Metric) *Metrics { 13 | return &Metrics{URI: URI, Metrics: metrics} 14 | } 15 | -------------------------------------------------------------------------------- /gateway/router/openapi/openapi3/content.go: -------------------------------------------------------------------------------- 1 | package openapi3 2 | 3 | // Content is specified by OpenAPI/Swagger 3.0 standard. 4 | type Content map[string]*MediaType 5 | -------------------------------------------------------------------------------- /gateway/router/openapi/openapi3/header.go: -------------------------------------------------------------------------------- 1 | package openapi3 2 | 3 | type ( 4 | Headers map[string]*Parameter 5 | ) 6 | -------------------------------------------------------------------------------- /gateway/router/openapi/openapi3/json.go: -------------------------------------------------------------------------------- 1 | package openapi3 2 | 3 | import ( 4 | "bytes" 5 | ) 6 | 7 | func mergeJSON(j1, j2 []byte) []byte { 8 | var result = make([]byte, len(j1)+len(j2)) 9 | copied := copy(result, j1) 10 | if copied == 2 { 11 | return j2 12 | } 13 | if index := bytes.LastIndex(j1, []byte("}")); index != -1 { 14 | result[index] = ',' 15 | index++ 16 | copied = copy(result[index:], j2[1:]) 17 | result = result[:index+copied] 18 | } 19 | return result 20 | } 21 | -------------------------------------------------------------------------------- /gateway/router/openapi/path.go: -------------------------------------------------------------------------------- 1 | package openapi 2 | 3 | import ( 4 | openapi "github.com/viant/datly/gateway/router/openapi/openapi3" 5 | "sync" 6 | ) 7 | 8 | type PathsBuilder struct { 9 | mux sync.Mutex 10 | paths openapi.Paths 11 | } 12 | 13 | func (b *PathsBuilder) AddPath(URI string, path *openapi.PathItem) { 14 | b.mux.Lock() 15 | defer b.mux.Unlock() 16 | 17 | b.paths[URI] = path 18 | } 19 | -------------------------------------------------------------------------------- /gateway/runtime/apigw/doc.go: -------------------------------------------------------------------------------- 1 | // Package apigw defines apigw lambda datly runtime 2 | package apigw 3 | -------------------------------------------------------------------------------- /gateway/runtime/apigw/policy/datly.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "dynamodb:*", 8 | "ssm:*", 9 | "kms:*", 10 | "s3:*", 11 | "lambda:*", 12 | "secretsmanager:*" 13 | ], 14 | "Resource": "*" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /gateway/runtime/apigw/resource/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "APIPrefix": "/v1/api/", 3 | "RouteURL": "s3://${configBucket}/${appName}/routes/", 4 | "DependencyURL": "s3://${configBucket}/${appName}/dependencies/", 5 | "UseCacheFS": true, 6 | "SyncFrequencyMs": 2000, 7 | "ColumnsDiscovery": true, 8 | "Secrets": [{ 9 | "Kind": "gcp", 10 | "URL": "aws://secretmanager/us-west-1/secret/dev/gcp/viant-e2e" 11 | }] 12 | } -------------------------------------------------------------------------------- /gateway/runtime/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.9 2 | 3 | RUN apk add --no-cache ca-certificates 4 | 5 | WORKDIR / 6 | 7 | COPY datly . 8 | 9 | EXPOSE 8080 10 | ENTRYPOINT ["/datly", "-c", "$configURL"] 11 | -------------------------------------------------------------------------------- /gateway/runtime/docker/Version: -------------------------------------------------------------------------------- 1 | 0.1.0 -------------------------------------------------------------------------------- /gateway/runtime/gcf/doc.go: -------------------------------------------------------------------------------- 1 | // Package gcf defines Google Cloud Functions entry point 2 | package gcf 3 | -------------------------------------------------------------------------------- /gateway/runtime/gcf/resource/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "APIPrefix": "/v1/api/", 3 | "RouteURL": "gs://${configBucket}/${appName}/routes/", 4 | "DependencyURL": "gs://${configBucket}/${appName}/dependencies/", 5 | "UseCacheFS": true, 6 | "SyncFrequencyMs": 2000 7 | } -------------------------------------------------------------------------------- /gateway/runtime/gcr/doc.go: -------------------------------------------------------------------------------- 1 | // Package gcr defines Google Cloud Exec entry point 2 | package gcr 3 | -------------------------------------------------------------------------------- /gateway/runtime/lambda/doc.go: -------------------------------------------------------------------------------- 1 | // Package lambda defines lambda datly runtime 2 | package lambda 3 | -------------------------------------------------------------------------------- /gateway/runtime/lambda/policy/datly.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "dynamodb:*", 8 | "ssm:*", 9 | "kms:*", 10 | "s3:*", 11 | "lambda:*", 12 | "secretsmanager:*" 13 | ], 14 | "Resource": "*" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /gateway/runtime/lambda/resource/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "APIPrefix": "/v1/api/", 3 | "RouteURL": "s3://${configBucket}/${appName}/routes/", 4 | "DependencyURL": "s3://${configBucket}/${appName}/dependencies/", 5 | "UseCacheFS": true, 6 | "SyncFrequencyMs": 2000, 7 | "Secrets": [ 8 | { 9 | "Kind": "gcp", 10 | "URL": "aws://secretmanager/us-west-1/secret/dev/gcp/viant-e2e" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /gateway/runtime/meta/auth.go: -------------------------------------------------------------------------------- 1 | package meta 2 | 3 | import ( 4 | "net/http" 5 | "strings" 6 | ) 7 | 8 | //IsAuthorized checks if request is authorized 9 | func IsAuthorized(request *http.Request, allowedSubset []string) bool { 10 | if len(allowedSubset) == 0 { 11 | return true 12 | } 13 | for _, allowed := range allowedSubset { 14 | if strings.HasPrefix(request.RemoteAddr, allowed) { 15 | return true 16 | } 17 | } 18 | return false 19 | } 20 | -------------------------------------------------------------------------------- /gateway/runtime/standalone/endpoint/config.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | // Config defines standalone app endpoint 4 | type Config struct { 5 | Port int 6 | ReadTimeoutMs int 7 | WriteTimeoutMs int 8 | MaxHeaderBytes int 9 | } 10 | 11 | // init initialises endpoint 12 | func (e *Config) Init() { 13 | if e.Port == 0 { 14 | e.Port = 8080 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /gateway/runtime/standalone/resource/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "APIPrefix": "/v1/api/", 3 | "RouteURL": "gs://${configBucket}/${appName}/routes/", 4 | "DependencyURL": "gs://${configBucket}/${appName}/dependencies/", 5 | "SyncFrequencyMs": 2000 6 | } -------------------------------------------------------------------------------- /internal/asset/json.go: -------------------------------------------------------------------------------- 1 | package asset 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/viant/toolbox" 6 | ) 7 | 8 | func EncodeJSON(any interface{}) ([]byte, error) { 9 | aMap := map[string]interface{}{} 10 | data, _ := json.Marshal(any) 11 | _ = json.Unmarshal(data, &aMap) 12 | compacted := map[string]interface{}{} 13 | _ = toolbox.CopyNonEmptyMapEntries(aMap, compacted) 14 | return json.MarshalIndent(compacted, "", "\t") 15 | } 16 | -------------------------------------------------------------------------------- /internal/asset/yaml.go: -------------------------------------------------------------------------------- 1 | package asset 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/viant/toolbox" 6 | "gopkg.in/yaml.v3" 7 | ) 8 | 9 | func EncodeYAML(any interface{}) ([]byte, error) { 10 | aMap := map[string]interface{}{} 11 | data, _ := json.Marshal(any) 12 | _ = json.Unmarshal(data, &aMap) 13 | compacted := map[string]interface{}{} 14 | _ = toolbox.CopyNonEmptyMapEntries(aMap, compacted) 15 | return yaml.Marshal(compacted) 16 | } 17 | -------------------------------------------------------------------------------- /internal/codegen/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### Grammar 4 | 5 | ### Parameter auto-detection 6 | 7 | ### Set Marker 8 | 9 | ### Struct types 10 | 11 | ### Relations 12 | 13 | 14 | -------------------------------------------------------------------------------- /internal/codegen/ast/binary.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | func NewBinary(x Expression, op string, y Expression) *BinaryExpr { 4 | return &BinaryExpr{X: x, Op: op, Y: y} 5 | } 6 | 7 | func (s *BinaryExpr) Generate(builder *Builder) (err error) { 8 | if err := s.X.Generate(builder); err != nil { 9 | return err 10 | } 11 | if err = builder.WriteString(" "); err != nil { 12 | return err 13 | } 14 | 15 | if err = builder.WriteString(s.Op); err != nil { 16 | return err 17 | } 18 | if err = builder.WriteString(" "); err != nil { 19 | return err 20 | } 21 | return s.Y.Generate(builder) 22 | } 23 | -------------------------------------------------------------------------------- /internal/codegen/ast/literal.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "strconv" 5 | "strings" 6 | ) 7 | 8 | func (s *LiteralExpr) Generate(builder *Builder) error { 9 | return builder.WriteString(s.Literal) 10 | } 11 | 12 | func NewQuotedLiteral(text string) *LiteralExpr { 13 | if !strings.HasPrefix(text, "\"") { 14 | text = strconv.Quote(text) 15 | } 16 | return &LiteralExpr{text} 17 | } 18 | 19 | func NewLiteral(text string) *LiteralExpr { 20 | return &LiteralExpr{text} 21 | } 22 | -------------------------------------------------------------------------------- /internal/codegen/ast/options.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | type Options struct { 4 | Lang string 5 | StateName string 6 | CallNotifier func(callExpr *CallExpr) (Expression, error) 7 | AssignNotifier func(assign *Assign) (Expression, error) 8 | SliceItemNotifier func(value, set *Ident) error 9 | WithoutBusinessLogic bool 10 | OnIfNotifier func(value *Condition) (Expression, error) 11 | WithLowerCaseIdent bool 12 | } 13 | -------------------------------------------------------------------------------- /internal/codegen/doc.go: -------------------------------------------------------------------------------- 1 | //Package codegen implements code generation logic 2 | package codegen 3 | -------------------------------------------------------------------------------- /internal/codegen/tmpl/dql.sqlx: -------------------------------------------------------------------------------- 1 | /* $RouteOption */ 2 | 3 | $Imports 4 | 5 | $Declaration 6 | 7 | $BusinessLogic -------------------------------------------------------------------------------- /internal/codegen/tmpl/entity.gox: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | var PackageName ="$Package" 5 | 6 | $GlobalDeclaration 7 | 8 | func init() { 9 | $Init 10 | } -------------------------------------------------------------------------------- /internal/codegen/tmpl/handler/has_key.gox: -------------------------------------------------------------------------------- 1 | func (c $IndexType) Has(key $KeyType) bool { 2 | _, ok := c[key] 3 | return ok 4 | } -------------------------------------------------------------------------------- /internal/codegen/tmpl/handler/index.gox: -------------------------------------------------------------------------------- 1 | package $PackageName 2 | 3 | $Content -------------------------------------------------------------------------------- /internal/codegen/tmpl/handler/index_by.gox: -------------------------------------------------------------------------------- 1 | type $ValueTypeSlice []*$ValueType 2 | type Indexed$ValueType map[$KeyType]*$ValueType 3 | 4 | func (c $ValueTypeSlice) IndexBy$IndexName() Indexed$ValueType { 5 | var result = Indexed$ValueType{} 6 | for i, item := range c { 7 | if item != nil { 8 | result[item.$IndexName] = c[i] 9 | } 10 | } 11 | return result 12 | } 13 | -------------------------------------------------------------------------------- /internal/codegen/tmpl/input.gox: -------------------------------------------------------------------------------- 1 | package $Package 2 | 3 | $Imports 4 | 5 | $EmbedFS 6 | 7 | func init() { 8 | $RegisterTypes 9 | } 10 | 11 | 12 | type Input struct { 13 | $Fields 14 | } 15 | 16 | 17 | ${EmbedFSFunc} 18 | -------------------------------------------------------------------------------- /internal/codegen/tmpl/input_init.gox: -------------------------------------------------------------------------------- 1 | package $Package 2 | 3 | import ( 4 | "context" 5 | "github.com/viant/xdatly/handler" 6 | ) 7 | 8 | func (i *Input) Init(ctx context.Context, sess handler.Session, output *Output) error { 9 | if err := sess.Stater().Bind(ctx, i); err != nil { 10 | return err 11 | } 12 | i.indexSlice() 13 | //TODO: add your custom init logic here 14 | return nil 15 | } 16 | 17 | 18 | func (i *Input) indexSlice() { 19 | $IndexSlice 20 | } 21 | -------------------------------------------------------------------------------- /internal/codegen/tmpl/output.gox: -------------------------------------------------------------------------------- 1 | 2 | func init() { 3 | $RegisterTypes 4 | } 5 | 6 | 7 | 8 | 9 | func (o *Output) setError(err error) { 10 | o.Status.Message = err.Error() 11 | o.Status.Status = "error" 12 | } 13 | -------------------------------------------------------------------------------- /internal/codegen/tmpl/plugin/checksum.gox: -------------------------------------------------------------------------------- 1 | package checksum 2 | 3 | // Code generated by datly; DO NOT EDIT. 4 | 5 | 6 | import "time" 7 | 8 | var GeneratedTime, _ = time.Parse(time.RFC3339, "$Time") 9 | -------------------------------------------------------------------------------- /internal/codegen/tmpl/plugin/dependency.gox: -------------------------------------------------------------------------------- 1 | package dependencies 2 | 3 | // Code generated by datly; DO NOT EDIT. 4 | 5 | $Imports 6 | -------------------------------------------------------------------------------- /internal/codegen/tmpl/plugin/main.gox: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | $Imports 4 | -------------------------------------------------------------------------------- /internal/converter/init.go: -------------------------------------------------------------------------------- 1 | package converter 2 | 3 | import "github.com/viant/govalidator" 4 | 5 | var aValidator *govalidator.Service 6 | 7 | func init() { 8 | aValidator = govalidator.New() 9 | } 10 | -------------------------------------------------------------------------------- /internal/inference/doc.go: -------------------------------------------------------------------------------- 1 | //Package inference defines process that automatically determines the data type of a variable or expression from database meta information 2 | package inference 3 | -------------------------------------------------------------------------------- /internal/inference/hint.go: -------------------------------------------------------------------------------- 1 | package inference 2 | 3 | import ( 4 | "encoding/json" 5 | "strings" 6 | ) 7 | 8 | func TryUnmarshalHint(hint string, any interface{}) error { 9 | hint = strings.TrimSpace(hint) 10 | if hint == "" { 11 | return nil 12 | } 13 | return HintToStruct(hint, any) 14 | } 15 | 16 | func HintToStruct(encoded string, aStructPtr interface{}) error { 17 | encoded = strings.ReplaceAll(encoded, "/*", "") 18 | encoded = strings.ReplaceAll(encoded, "*/", "") 19 | encoded = strings.TrimSpace(encoded) 20 | return json.Unmarshal([]byte(encoded), aStructPtr) 21 | } 22 | -------------------------------------------------------------------------------- /internal/msg/message.go: -------------------------------------------------------------------------------- 1 | package msg 2 | 3 | type Message struct { 4 | Level string 5 | Source string 6 | Kind string 7 | Message string 8 | } 9 | -------------------------------------------------------------------------------- /internal/msg/messages.go: -------------------------------------------------------------------------------- 1 | package msg 2 | 3 | import "fmt" 4 | 5 | type Messages struct { 6 | Items []*Message 7 | } 8 | 9 | func (m *Messages) AddWarning(source, kind, message string) { 10 | fmt.Printf("[WARN] %v\n", message) 11 | msg := &Message{ 12 | Level: "warn", 13 | Source: source, 14 | Kind: kind, 15 | Message: message, 16 | } 17 | m.Items = append(m.Items, msg) 18 | } 19 | -------------------------------------------------------------------------------- /internal/plugin/packages.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import "golang.org/x/tools/go/packages" 4 | 5 | type Packages []*packages.Package 6 | 7 | func (p *Packages) Append(pkg *packages.Package) { 8 | if len(*p) == 0 { 9 | *p = append(*p, pkg) 10 | return 11 | } 12 | for _, item := range *p { 13 | if item.ID == pkg.ID { 14 | return 15 | } 16 | } 17 | *p = append(*p, pkg) 18 | } 19 | func (p Packages) Index() map[string]*packages.Package { 20 | var result = make(map[string]*packages.Package, len(p)) 21 | for i := range p { 22 | result[p[i].ID] = p[i] 23 | } 24 | return result 25 | } 26 | -------------------------------------------------------------------------------- /internal/setter/ptr.go: -------------------------------------------------------------------------------- 1 | package setter 2 | 3 | func StringPtr(v string) *string { 4 | return &v 5 | } 6 | 7 | func StringsPtr(v ...string) *[]string { 8 | return &v 9 | } 10 | 11 | func BoolPtr(v bool) *bool { 12 | return &v 13 | } 14 | 15 | func IntPtr(v int) *int { 16 | return &v 17 | } 18 | -------------------------------------------------------------------------------- /internal/tests/log.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | var loggingHeaderEnabled = os.Getenv("ENABLE_LOGGING") == "true" 9 | 10 | func LogHeader(header string) { 11 | //if !loggingHeaderEnabled { 12 | // return 13 | //} 14 | 15 | fmt.Println(header) 16 | } 17 | -------------------------------------------------------------------------------- /internal/translator/README.md: -------------------------------------------------------------------------------- 1 | ### Grammar 2 | 3 | # Repository resources 4 | 5 | - connections 6 | - constants 7 | - caches 8 | - messageBuses 9 | 10 | ### Parameter auto-detection 11 | 12 | ### Struct types 13 | 14 | ### Relations 15 | 16 | ### Codecs 17 | 18 | ### Hints 19 | 20 | -------------------------------------------------------------------------------- /internal/translator/cache.go: -------------------------------------------------------------------------------- 1 | package translator 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func (r *Repository) ensureCache(ctx context.Context) error { 8 | if resource, _ := r.loadDependency(ctx, "cache.yaml"); resource != nil { 9 | for _, cache := range resource.CacheProviders { 10 | r.Caches.Append(cache) 11 | } 12 | } 13 | return nil 14 | 15 | } 16 | -------------------------------------------------------------------------------- /internal/translator/doc.go: -------------------------------------------------------------------------------- 1 | // Package translator implements dql to datly rule translator 2 | package translator 3 | -------------------------------------------------------------------------------- /internal/translator/function/init.go: -------------------------------------------------------------------------------- 1 | package function 2 | 3 | func init() { 4 | _registry.Register(&connector{}) 5 | _registry.Register(&cache{}) 6 | _registry.Register(&limit{}) 7 | _registry.Register(&orderBy{}) 8 | _registry.Register(&cardinality{}) 9 | _registry.Register(&allownulls{}) 10 | _registry.Register(&matchStrategy{}) 11 | _registry.Register(&batchSize{}) 12 | _registry.Register(&partitioner{}) 13 | _registry.Register(&publishParent{}) 14 | _registry.Register(&relationalConcurrency{}) 15 | } 16 | -------------------------------------------------------------------------------- /internal/translator/parser/matchers/any.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "github.com/viant/parsly" 5 | ) 6 | 7 | type any struct { 8 | } 9 | 10 | func (a *any) Match(cursor *parsly.Cursor) (matched int) { 11 | if cursor.Pos < cursor.InputSize { 12 | return 1 13 | } 14 | 15 | return 0 16 | } 17 | 18 | func NewAny() parsly.Matcher { 19 | return &any{} 20 | } 21 | -------------------------------------------------------------------------------- /mcp/extension/handler_test.go: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | 10 | i := Handler{} 11 | fmt.Println(i) 12 | } 13 | -------------------------------------------------------------------------------- /repository/codegen/context.go: -------------------------------------------------------------------------------- 1 | package codegen 2 | 3 | import "context" 4 | 5 | var generatorKey string 6 | 7 | func IsGeneratorContext(ctx context.Context) bool { 8 | return ctx.Value(generatorKey) != nil 9 | } 10 | 11 | func WithGeneratorContext(ctx context.Context) context.Context { 12 | return context.WithValue(ctx, generatorKey, true) 13 | } 14 | -------------------------------------------------------------------------------- /repository/codegen/register.gox: -------------------------------------------------------------------------------- 1 | // Code generated by datly. DO NOT EDIT. 2 | // This file was automatically generated and should not be modified manually. 3 | 4 | 5 | func init() { 6 | core.RegisterType("$PackageName", "${Name}Input", reflect.TypeOf(${Name}Input{}), checksum.GeneratedTime) 7 | core.RegisterType("$PackageName", "${Name}Output", reflect.TypeOf(${Name}Output{}), checksum.GeneratedTime) 8 | } 9 | -------------------------------------------------------------------------------- /repository/content/config.go: -------------------------------------------------------------------------------- 1 | package content 2 | 3 | import "github.com/viant/sqlx/io/load/reader/csv" 4 | 5 | type CSVConfig struct { 6 | Separator string 7 | NullValue string 8 | _config *csv.Config 9 | InputMarshaller *csv.Marshaller 10 | OutputMarshaller *csv.Marshaller 11 | } 12 | -------------------------------------------------------------------------------- /repository/content/const.go: -------------------------------------------------------------------------------- 1 | package content 2 | 3 | const ( 4 | JSONFormat = "json" 5 | XMLFormat = "xml" 6 | XLSFormat = "xls" 7 | CSVFormat = "csv" 8 | JSONDataFormatTabular = "tabular" 9 | ) 10 | 11 | const ( 12 | XLSContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" 13 | CSVContentType = "text/csv" 14 | JSONContentType = "application/json" 15 | TabularJSONFormat = "application/json" 16 | XMLContentType = "application/xml" 17 | ) 18 | -------------------------------------------------------------------------------- /repository/contract/status.go: -------------------------------------------------------------------------------- 1 | package contract 2 | 3 | import ( 4 | expand "github.com/viant/datly/service/executor/expand" 5 | "github.com/viant/xdatly/handler/response" 6 | ) 7 | 8 | // TODO move it to some other package 9 | func StatusSuccess(state *expand.State) response.Status { 10 | status := response.Status{Status: "ok"} 11 | if state != nil { 12 | status.Extras = state.ResponseBuilder.Content 13 | } 14 | 15 | return status 16 | } 17 | -------------------------------------------------------------------------------- /repository/locator/meta/keys/meta.go: -------------------------------------------------------------------------------- 1 | package keys 2 | 3 | const ( //meta kind 4 | 5 | ViewID = "view.id" 6 | ViewName = "view.name" 7 | ViewDescription = "view.description" 8 | ) 9 | -------------------------------------------------------------------------------- /repository/locator/meta/keys/types.go: -------------------------------------------------------------------------------- 1 | package keys 2 | 3 | import ( 4 | "github.com/viant/xreflect" 5 | "reflect" 6 | ) 7 | 8 | var Types = map[string]reflect.Type{ 9 | //component/View related keys 10 | ViewID: xreflect.StringType, 11 | ViewName: xreflect.StringType, 12 | ViewDescription: xreflect.StringType, 13 | } 14 | -------------------------------------------------------------------------------- /repository/logging/config.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | type Config struct { 4 | EnableTracing *bool 5 | EnableAudit *bool 6 | IncludeSQL *bool 7 | } 8 | 9 | func (c *Config) IsTracingEnabled() bool { 10 | if c.EnableTracing == nil { 11 | return false 12 | } 13 | return *c.EnableTracing 14 | } 15 | 16 | func (c *Config) IsAuditEnabled() bool { 17 | if c.EnableAudit == nil { 18 | return true 19 | } 20 | return *c.EnableAudit 21 | } 22 | 23 | func (c *Config) ShallIncludeSQL() bool { 24 | if c.IncludeSQL == nil { 25 | return false 26 | } 27 | return *c.IncludeSQL 28 | } 29 | -------------------------------------------------------------------------------- /repository/path/compression.go: -------------------------------------------------------------------------------- 1 | package path 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type ( 8 | Compression struct { 9 | MinSizeKb int `yaml:"MinSizeKb,omitempty"` 10 | } 11 | 12 | Redirect struct { 13 | StorageURL string `yaml:"StorageURL,omitempty"` ///github.com/viant/datly/v0/app/lambda/lambda/proxy.go 14 | MinSizeKb int `yaml:"MinSizeKb,omitempty"` 15 | TimeToLiveMs int `yaml:"TimeToLiveMs,omitempty"` 16 | } 17 | ) 18 | 19 | func (r *Redirect) TimeToLive() time.Duration { 20 | return time.Duration(r.TimeToLiveMs) * time.Millisecond 21 | } 22 | -------------------------------------------------------------------------------- /repository/path/logger.go: -------------------------------------------------------------------------------- 1 | package path 2 | 3 | type Logger struct { 4 | MinExecutionMs *int 5 | } 6 | -------------------------------------------------------------------------------- /repository/redirect/handler.go: -------------------------------------------------------------------------------- 1 | package redirect 2 | 3 | import "github.com/viant/datly/view/state" 4 | 5 | type Handler struct { 6 | URL string 7 | Input *state.Parameters 8 | } 9 | -------------------------------------------------------------------------------- /repository/resource.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "context" 5 | "github.com/viant/datly/repository/version" 6 | "github.com/viant/datly/view" 7 | "time" 8 | ) 9 | 10 | // Resources represents a resource 11 | type Resources interface { 12 | AddResource(key string, aResource *view.Resource) 13 | Has(key string) bool 14 | Lookup(key string) (*version.Resource, error) 15 | Substitutes() map[string]view.Substitutes 16 | IsCheckDue(t time.Time) bool 17 | SyncChanges(ctx context.Context) (bool, error) 18 | } 19 | -------------------------------------------------------------------------------- /service/auth/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/viant/datly/service/auth/secret" 5 | "github.com/viant/scy/auth/cognito" 6 | "github.com/viant/scy/auth/firebase" 7 | "github.com/viant/scy/auth/jwt/signer" 8 | "github.com/viant/scy/auth/jwt/verifier" 9 | ) 10 | 11 | type ( 12 | Config struct { 13 | Secrets []*secret.Resource 14 | JWTValidator *verifier.Config 15 | JwtSigner *signer.Config 16 | Cognito *cognito.Config 17 | Firebase *firebase.Config 18 | DependencyURL string 19 | } 20 | ) 21 | -------------------------------------------------------------------------------- /service/auth/mock/jwt/hmac.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/service/auth/mock/jwt/hmac.enc -------------------------------------------------------------------------------- /service/auth/mock/jwt/private.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/service/auth/mock/jwt/private.enc -------------------------------------------------------------------------------- /service/auth/mock/jwt/public.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/viant/datly/0ecd951c85bb58da728bbdf270fbe53506d9cf93/service/auth/mock/jwt/public.enc -------------------------------------------------------------------------------- /service/auth/secret/resource.go: -------------------------------------------------------------------------------- 1 | package secret 2 | 3 | import "github.com/viant/scy" 4 | 5 | // Kind represent resource kind 6 | type Kind string 7 | 8 | // Resource represents secret resource 9 | type Resource struct { 10 | scy.Resource 11 | Kind Kind 12 | } 13 | -------------------------------------------------------------------------------- /service/auth/token/authorization.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "github.com/viant/scy/auth" 5 | "strings" 6 | ) 7 | 8 | type Authorization struct { 9 | Type string 10 | Raw string 11 | RawToken string 12 | OAuth auth.Token 13 | } 14 | 15 | func NewAuthorization(raw string) *Authorization { 16 | result := &Authorization{ 17 | Raw: raw, 18 | } 19 | if index := strings.Index(raw, " "); index != -1 { 20 | result.Type = raw[:index] 21 | result.RawToken = raw[index+1:] 22 | } 23 | return result 24 | } 25 | -------------------------------------------------------------------------------- /service/const.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | // Type defines service type 4 | type Type string 5 | 6 | const ( 7 | TypeReader Type = "Reader" 8 | TypeExecutor Type = "Executor" 9 | ) 10 | -------------------------------------------------------------------------------- /service/dbms/doc.go: -------------------------------------------------------------------------------- 1 | // Package dbms defines service to crate or check table schema 2 | package dbms 3 | -------------------------------------------------------------------------------- /service/dbms/provider/sql.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "github.com/viant/sqlx/option" 5 | "reflect" 6 | ) 7 | 8 | type SqlSource interface { 9 | CreateTable(recordType reflect.Type, tableName string, tagName option.Tag, autogeneratePk bool) (*Table, error) 10 | RecordType(recordType reflect.Type, tagName option.Tag) (reflect.Type, error) 11 | } 12 | -------------------------------------------------------------------------------- /service/dbms/provider/table.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "github.com/viant/datly/view" 5 | "reflect" 6 | ) 7 | 8 | type Table struct { 9 | View *view.View 10 | SQL string 11 | Relations []*Table 12 | RecordType reflect.Type 13 | } 14 | -------------------------------------------------------------------------------- /service/executor/db.go: -------------------------------------------------------------------------------- 1 | package executor 2 | 3 | import ( 4 | "context" 5 | "database/sql" 6 | "github.com/viant/sqlx/metadata/info" 7 | ) 8 | 9 | type DBSource interface { 10 | Db(ctx context.Context) (*sql.DB, error) 11 | Dialect(ctx context.Context) (*info.Dialect, error) 12 | } 13 | -------------------------------------------------------------------------------- /service/executor/expand/fn.go: -------------------------------------------------------------------------------- 1 | package expand 2 | 3 | import ( 4 | "fmt" 5 | "github.com/viant/velty/ast/expr" 6 | ) 7 | 8 | func unexpectedArgType(position int, expected interface{}, got interface{}) error { 9 | return fmt.Errorf("unexpected arg[%v] type, expected %T, got %T", position, expected, got) 10 | } 11 | 12 | func checkArgsSize(call *expr.Call, size int) error { 13 | if len(call.Args) != size { 14 | return fmt.Errorf("unexpected number of function %v arguments, expected 1 got %v", fnQuery, len(call.Args)) 15 | } 16 | return nil 17 | } 18 | -------------------------------------------------------------------------------- /service/executor/expand/fn_changed.go: -------------------------------------------------------------------------------- 1 | package expand 2 | 3 | import ( 4 | "github.com/viant/godiff" 5 | "github.com/viant/velty/est/op" 6 | "github.com/viant/xreflect" 7 | ) 8 | 9 | const fnChanged = "Changed" 10 | 11 | var funcChanged = &op.TypeFunc{ 12 | ResultType: xreflect.BoolType, 13 | Name: fnChanged, 14 | Handler: func(changes *godiff.ChangeLog) bool { 15 | return changes.Size() != 0 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /service/executor/expand/fn_nop.go: -------------------------------------------------------------------------------- 1 | package expand 2 | 3 | import ( 4 | "github.com/viant/datly/view/keywords" 5 | "github.com/viant/velty/functions" 6 | ) 7 | 8 | var fnNop = keywords.AddAndGet("Nop", &functions.Entry{ 9 | Metadata: &keywords.StandaloneFn{}, 10 | Handler: nil, 11 | }) 12 | 13 | type noper struct { 14 | } 15 | 16 | func (n noper) Nop(any ...interface{}) string { 17 | return "" 18 | } 19 | -------------------------------------------------------------------------------- /service/executor/expand/init.go: -------------------------------------------------------------------------------- 1 | package expand 2 | 3 | import ( 4 | "github.com/viant/datly/view/keywords" 5 | "reflect" 6 | ) 7 | 8 | func init() { 9 | ctxType := reflect.TypeOf(Context{}) 10 | keywords.RegisterType("", ctxType) 11 | } 12 | -------------------------------------------------------------------------------- /service/executor/extension/options.go: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | // Option represen session option 4 | type Option func(s *Session) 5 | 6 | type options []Option 7 | 8 | func (o options) Apply(session *Session) { 9 | for _, opt := range o { 10 | opt(session) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /service/executor/extension/response.go: -------------------------------------------------------------------------------- 1 | package extension 2 | -------------------------------------------------------------------------------- /service/executor/sequencer/sequence.go: -------------------------------------------------------------------------------- 1 | package sequencer 2 | 3 | // Sequence represents a sequence 4 | type Sequence struct { 5 | Value int64 6 | IncrementBy int64 7 | } 8 | -------------------------------------------------------------------------------- /service/executor/stmt.go: -------------------------------------------------------------------------------- 1 | package executor 2 | 3 | type StmtIterator interface { 4 | HasNext() bool 5 | Next() interface{} 6 | HasAny() bool 7 | } 8 | -------------------------------------------------------------------------------- /service/jobs/inserter.go: -------------------------------------------------------------------------------- 1 | package jobs 2 | 3 | import ( 4 | "context" 5 | "github.com/viant/xdatly/handler/async" 6 | ) 7 | 8 | func (s *Service) CreateJob(ctx context.Context, job *async.Job) error { 9 | db, err := s.connector.DB() 10 | if err != nil { 11 | return err 12 | } 13 | _, _, err = s.inserter.Exec(ctx, job, db) 14 | if err != nil { 15 | return err 16 | } 17 | 18 | return nil 19 | } 20 | -------------------------------------------------------------------------------- /service/jobs/internal/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Generate jobs repository with the following command 3 | 4 | datly translate -s=rules -c='dev|mysql|root:dev@tcp(127.0.0.1:3306)/dev?parseTime=true' -u=jobs 5 | 6 | -------------------------------------------------------------------------------- /service/jobs/internal/rules/deactivate.sql: -------------------------------------------------------------------------------- 1 | /* {"URI":"/deactivate", "Method":"GET"} */ 2 | 3 | #set($_ = $Module(query/module)) 4 | #set($_ = $Views<[]string>(query/view)) 5 | 6 | #if(($Unsafe.Module=="") && ($Unsafe.Views.Length() == 0)) 7 | $logger.Fatal("both module and view were empty") 8 | #end 9 | 10 | UPDATE DATLY_JOBS SET Deactivated = 1 WHERE 11 | #if($Unsafe.Views.Length() > 0) 12 | $criteria.In("ID", $Views) 13 | #elseif($Has.Module==true) 14 | Module = $Module 15 | #end 16 | ; 17 | -------------------------------------------------------------------------------- /service/jobs/internal/rules/jobs.sql: -------------------------------------------------------------------------------- 1 | /* { 2 | "URI":"/{Source}/", 3 | "Include":[ 4 | "shared/predicates.yaml", 5 | "shared/input.sqlx", 6 | "shared/output.sqlx" 7 | ] 8 | } */ 9 | 10 | SELECT jobs.* 11 | FROM (SELECT * 12 | FROM DATLY_JOBS t 13 | WHERE 1 = 1 14 | ${predicate.Builder().CombineOr( 15 | $predicate.FilterGroup(0, "AND") 16 | ).Build("AND")} 17 | ) jobs 18 | 19 | -------------------------------------------------------------------------------- /service/jobs/internal/rules/shared/input.sqlx: -------------------------------------------------------------------------------- 1 | 2 | #set( $_ = $Source(path/Source).WithPredicate(0,'kind')) 3 | #set( $_ = $Module(query/module).WithPredicate(0,'in','t','Module')) 4 | #set( $_ = $Views<[]string>(query/view).WithPredicate(0,'in','t','MainView')) 5 | #set( $_ = $User<[]string>(query/user).WithPredicate(0,'contains','t','UserEmail')) 6 | -------------------------------------------------------------------------------- /service/jobs/internal/rules/shared/output.sqlx: -------------------------------------------------------------------------------- 1 | 2 | 3 | #set( $_ = $Jobs(output/view)) 4 | #set( $_ = $Status(output/status)) 5 | -------------------------------------------------------------------------------- /service/jobs/internal/rules/shared/predicates.yaml: -------------------------------------------------------------------------------- 1 | Predicates: 2 | 3 | - Name: kind 4 | Source: | 5 | #if($Unsafe.Source=="active") 6 | Deactivated = 0 AND STATUS = 'DONE' AND ExpiryTime > CURRENT_TIMESTAMP 7 | #elseif ($Unsafe.Source=="pending") 8 | Deactivated = 0 AND STATUS IN('RUNNING','PENDING') 9 | AND CreationTime > DATE_ADD(CURRENT_TIMESTAMP, INTERVAL -24 HOUR) 10 | #else 11 | ID = $Source 12 | #end -------------------------------------------------------------------------------- /service/jobs/resource.go: -------------------------------------------------------------------------------- 1 | package jobs 2 | -------------------------------------------------------------------------------- /service/jobs/updater.go: -------------------------------------------------------------------------------- 1 | package jobs 2 | 3 | import ( 4 | "context" 5 | "github.com/viant/xdatly/handler/async" 6 | ) 7 | 8 | // default ->, description -> validate: required, ptr vs non-ptr 9 | func (s *Service) UpdateJob(ctx context.Context, job *async.Job) error { 10 | db, err := s.connector.DB() 11 | if err != nil { 12 | return err 13 | } 14 | _, err = s.updater.Exec(ctx, job, db) 15 | if err != nil { 16 | return err 17 | } 18 | return nil 19 | } 20 | -------------------------------------------------------------------------------- /service/reader/events.go: -------------------------------------------------------------------------------- 1 | package reader 2 | 3 | type Event string 4 | 5 | const ( 6 | Pending Event = "Pending" 7 | Error Event = "Error" 8 | Success Event = "Success" 9 | ) 10 | -------------------------------------------------------------------------------- /service/reader/lifecycle.go: -------------------------------------------------------------------------------- 1 | package reader 2 | 3 | import "context" 4 | 5 | // OnFetcher lifecycle interface that if entity implements, OnFetch(ctx context.NormalizeObject) is call after record is fetched from db 6 | type OnFetcher interface { 7 | OnFetch(ctx context.Context) error 8 | } 9 | 10 | // OnRelationer lifecycle interface that if entity implements, OnRelation(ctx context.NormalizeObject) is call after relation is assembled 11 | type OnRelationer interface { 12 | OnRelation(ctx context.Context) 13 | } 14 | 15 | type OnRelationerConcurrency interface { 16 | Concurrency() int 17 | } 18 | -------------------------------------------------------------------------------- /service/reader/slice.go: -------------------------------------------------------------------------------- 1 | package reader 2 | 3 | func sliceWithLimit(aSlice []interface{}, from, to int) ([]interface{}, int) { 4 | if len(aSlice) > to { 5 | return aSlice[from:to], to - from 6 | } 7 | 8 | return aSlice[from:], len(aSlice) - from 9 | } 10 | -------------------------------------------------------------------------------- /service/reader/sql_meta.go: -------------------------------------------------------------------------------- 1 | package reader 2 | 3 | import "strings" 4 | 5 | type reservedMeta struct { 6 | or bool 7 | and bool 8 | where bool 9 | raw bool 10 | } 11 | 12 | func hasKeyword(SQL, keyword string) *reservedMeta { 13 | return &reservedMeta{ 14 | or: strings.Contains(SQL, "$OR_"+keyword[1:]), 15 | and: strings.Contains(SQL, "$AND_"+keyword[1:]), 16 | where: strings.Contains(SQL, "$WHERE_"+keyword[1:]), 17 | raw: strings.Contains(SQL, keyword), 18 | } 19 | } 20 | 21 | func (r *reservedMeta) has() bool { 22 | return r.or || r.raw || r.and || r.where 23 | } 24 | -------------------------------------------------------------------------------- /service/reader/testdata/cases/case001_schema/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case001_schema/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: events 5 | Columns: 6 | - Name: id 7 | DataType: Int 8 | - Name: quantity 9 | DataType: Float 10 | - Name: event_type_id 11 | DataType: Int 12 | Schema: 13 | Name: events 14 | Connectors: 15 | - Name: db 16 | Driver: sqlite3 17 | DSN: "./testdata/db/db.db" 18 | -------------------------------------------------------------------------------- /service/reader/testdata/cases/case002_from/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case002_from/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: events 5 | From: SELECT COALESCE(id,0) AS id, quantity, event_type_id, timestamp, user_id FROM events 6 | Selector: 7 | Constraints: 8 | Criteria: true 9 | Filterable: 10 | - event_type_id 11 | Connectors: 12 | - Name: db 13 | Driver: sqlite3 14 | DSN: "./testdata/db/db.db" -------------------------------------------------------------------------------- /service/reader/testdata/cases/case003_exclude/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case003_exclude/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: events 5 | Default: {} 6 | Exclude: 7 | - id 8 | - event_type_id 9 | Selector: 10 | Constraints: 11 | Filterable: 12 | - quantity 13 | Connectors: 14 | - Name: db 15 | Driver: sqlite3 16 | DSN: "./testdata/db/db.db" -------------------------------------------------------------------------------- /service/reader/testdata/cases/case004_selector/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case004_selector/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: events 5 | Selector: 6 | Limit: 2 7 | OrderBy: timestamp 8 | Constraints: 9 | Limit: true 10 | OrderBy: true 11 | Offset: true 12 | Exclude: 13 | - id 14 | - event_type_id 15 | Connectors: 16 | - Name: db 17 | Driver: sqlite3 18 | DSN: "./testdata/db/db.db" -------------------------------------------------------------------------------- /service/reader/testdata/cases/case005_column_expression/populate_db/foos.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "price": 125.5, 6 | "name": "foo" 7 | }, 8 | { 9 | "id": 2, 10 | "price": 250, 11 | "name": "another foo" 12 | }, 13 | { 14 | "id": 3, 15 | "price": 375.5, 16 | "name": "yet another foo" 17 | } 18 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case005_column_expression/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: foos 5 | Schema: 6 | Name: foo 7 | Columns: 8 | - Name: id 9 | DataType: Int 10 | - Name: name 11 | Expression: Upper(name) 12 | DataType: String 13 | Connectors: 14 | - Name: db 15 | Driver: sqlite3 16 | DSN: "./testdata/db/db.db" -------------------------------------------------------------------------------- /service/reader/testdata/cases/case006_client_selector/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case006_client_selector/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: events 5 | Table: events 6 | Columns: 7 | - Name: id 8 | DataType: Int 9 | - Name: timestamp 10 | DataType: String 11 | - Name: quantity 12 | DataType: Float 13 | Selector: 14 | Constraints: 15 | Columns: true 16 | OrderBy: true 17 | Filterable: 18 | - id 19 | - quantity 20 | Connectors: 21 | - Name: db 22 | Driver: sqlite3 23 | DSN: "./testdata/db/db.db" 24 | -------------------------------------------------------------------------------- /service/reader/testdata/cases/case007_one_to_one/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case008_many_to_one/populate_db/accounts.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "User_id": 1, 6 | "Name": "John account" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "Anna account", 11 | "User_id": 2 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Another John account", 16 | "User_id": 1 17 | } 18 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case008_many_to_one/populate_db/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "Name": "John", 6 | "Role": "" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "David", 11 | "Role": "" 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Anna", 16 | "Role": "" 17 | }, 18 | { 19 | "Id": 4, 20 | "Name": "Kamil", 21 | "Role": "ADMIN" 22 | }, 23 | { 24 | "Id": 5, 25 | "Name": "Bob", 26 | "Role": "ADMIN" 27 | } 28 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case009_without_column/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case010_view_parameter/populate_db/accounts.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "User_id": 1, 6 | "Name": "John account" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "Anna account", 11 | "User_id": 2 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Another John account", 16 | "User_id": 1 17 | } 18 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case010_view_parameter/populate_db/datly_acl.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "subject": "Kamil", 5 | "criteria": "ROLE IN ('ADMIN')", 6 | "data_view": "users_accounts" 7 | } 8 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case010_view_parameter/populate_db/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "Name": "John", 6 | "Role": "" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "David", 11 | "Role": "" 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Anna", 16 | "Role": "" 17 | }, 18 | { 19 | "Id": 4, 20 | "Name": "Kamil", 21 | "Role": "ADMIN" 22 | }, 23 | { 24 | "Id": 5, 25 | "Name": "Bob", 26 | "Role": "ADMIN" 27 | } 28 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case011_read_all_one_to_one/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case012_many_to_one/populate_db/accounts.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "User_id": 1, 6 | "Name": "John account" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "Anna account", 11 | "User_id": 2 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Another John account", 16 | "User_id": 1 17 | } 18 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case012_many_to_one/populate_db/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "Name": "John", 6 | "Role": "" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "David", 11 | "Role": "" 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Anna", 16 | "Role": "" 17 | }, 18 | { 19 | "Id": 4, 20 | "Name": "Kamil", 21 | "Role": "ADMIN" 22 | }, 23 | { 24 | "Id": 5, 25 | "Name": "Bob", 26 | "Role": "ADMIN" 27 | } 28 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case012_many_to_one/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: users 5 | Table: users 6 | 7 | - Connector: 8 | Ref: db 9 | Name: accounts 10 | Table: accounts 11 | 12 | - Connector: 13 | Ref: db 14 | Name: users_accounts 15 | Ref: users 16 | With: 17 | - Name: user_accounts-rel 18 | Holder: Accounts 19 | Column: id 20 | IncludeColumn: false 21 | Cardinality: Many 22 | Of: 23 | Ref: accounts 24 | Column: user_id 25 | Connectors: 26 | - Name: db 27 | Driver: sqlite3 28 | DSN: "./testdata/db/db.db" 29 | -------------------------------------------------------------------------------- /service/reader/testdata/cases/case012_read_all_many_to_one/populate_db/accounts.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "User_id": 1, 6 | "Name": "John account" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "Anna account", 11 | "User_id": 2 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Another John account", 16 | "User_id": 1 17 | } 18 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case012_read_all_many_to_one/populate_db/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "Name": "John", 6 | "Role": "" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "David", 11 | "Role": "" 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Anna", 16 | "Role": "" 17 | }, 18 | { 19 | "Id": 4, 20 | "Name": "Kamil", 21 | "Role": "ADMIN" 22 | }, 23 | { 24 | "Id": 5, 25 | "Name": "Bob", 26 | "Role": "ADMIN" 27 | } 28 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case013_read_all_batch_size/populate_db/articles.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "content": "Lorem ipsum", 6 | "lang_id": 2 7 | }, 8 | { 9 | "id": 2, 10 | "content": "dolor sit amet", 11 | "lang_id": 12 12 | }, 13 | { 14 | "id": 3, 15 | "content": "consectetur adipiscing elit", 16 | "lang_id": 13 17 | }, 18 | { 19 | "id": 4, 20 | "content": "sed do eiusmod tempor incididunt", 21 | "lang_id": 9 22 | }, 23 | { 24 | "id": 5, 25 | "content": "content without lang", 26 | "lang_id": 0 27 | } 28 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case014_T_one_to_one/populate_db/articles.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "content": "Lorem ipsum", 6 | "lang_id": 2 7 | }, 8 | { 9 | "id": 2, 10 | "content": "dolor sit amet", 11 | "lang_id": 12 12 | }, 13 | { 14 | "id": 3, 15 | "content": "consectetur adipiscing elit", 16 | "lang_id": 13 17 | }, 18 | { 19 | "id": 4, 20 | "content": "sed do eiusmod tempor incididunt", 21 | "lang_id": 9 22 | }, 23 | { 24 | "id": 5, 25 | "content": "content without lang", 26 | "lang_id": 0 27 | } 28 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case015_path_parameter/populate_db/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "Name": "John", 6 | "Role": "" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "David", 11 | "Role": "" 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Anna", 16 | "Role": "" 17 | }, 18 | { 19 | "Id": 4, 20 | "Name": "Kamil", 21 | "Role": "ADMIN" 22 | }, 23 | { 24 | "Id": 5, 25 | "Name": "Bob", 26 | "Role": "ADMIN" 27 | } 28 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case015_path_parameter/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: users 5 | Table: users 6 | Template: 7 | Source: "SELECT * FROM USERS WHERE ID = ${Unsafe.UserId}" 8 | Schema: 9 | Name: user_params 10 | Parameters: 11 | - Ref: UserId 12 | 13 | Connectors: 14 | - Name: db 15 | Driver: sqlite3 16 | DSN: "./testdata/db/db.db" 17 | 18 | Parameters: 19 | - Name: UserId 20 | In: 21 | Kind: path 22 | Name: userId 23 | Required: true 24 | Schema: 25 | DataType: int 26 | -------------------------------------------------------------------------------- /service/reader/testdata/cases/case016_query_parameter/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: otherdb 4 | Name: languages 5 | Template: 6 | Source: "SELECT * FROM LANGUAGES WHERE code LIKE '${Unsafe.Language}%'" 7 | Schema: 8 | Name: lang_params 9 | Parameters: 10 | - Ref: Language 11 | 12 | Connectors: 13 | - Name: otherdb 14 | Driver: sqlite3 15 | DSN: "./testdata/db/other.db" 16 | 17 | Parameters: 18 | - Name: Language 19 | In: 20 | Kind: query 21 | Name: lang 22 | Required: true 23 | Schema: 24 | DataType: string 25 | -------------------------------------------------------------------------------- /service/reader/testdata/cases/case017_header_parameter/populate_db/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "Name": "John", 6 | "Role": "" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "David", 11 | "Role": "" 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Anna", 16 | "Role": "" 17 | }, 18 | { 19 | "Id": 4, 20 | "Name": "Kamil", 21 | "Role": "ADMIN" 22 | }, 23 | { 24 | "Id": 5, 25 | "Name": "Bob", 26 | "Role": "ADMIN" 27 | } 28 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case017_header_parameter/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: users 5 | Table: users 6 | Template: 7 | Source: "SELECT * FROM USERS WHERE NAME LIKE '${Unsafe.User_name}%'" 8 | Schema: 9 | Name: header_params 10 | Parameters: 11 | - Ref: User_name 12 | 13 | Connectors: 14 | - Name: db 15 | Driver: sqlite3 16 | DSN: "./testdata/db/db.db" 17 | 18 | Parameters: 19 | - Name: User_name 20 | In: 21 | Kind: header 22 | Name: user-name 23 | Required: true 24 | Schema: 25 | DataType: string 26 | -------------------------------------------------------------------------------- /service/reader/testdata/cases/case018_cookie_parameter/populate_db/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "Name": "John", 6 | "Role": "" 7 | }, 8 | { 9 | "Id": 2, 10 | "Name": "David", 11 | "Role": "" 12 | }, 13 | { 14 | "Id": 3, 15 | "Name": "Anna", 16 | "Role": "" 17 | }, 18 | { 19 | "Id": 4, 20 | "Name": "Kamil", 21 | "Role": "ADMIN" 22 | }, 23 | { 24 | "Id": 5, 25 | "Name": "Bob", 26 | "Role": "ADMIN" 27 | } 28 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case018_cookie_parameter/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: users 5 | Table: users 6 | Template: 7 | Source: "SELECT * FROM USERS WHERE ID = ${Unsafe.UserId}" 8 | Schema: 9 | Name: user_params 10 | Parameters: 11 | - Ref: UserId 12 | 13 | Connectors: 14 | - Name: db 15 | Driver: sqlite3 16 | DSN: "./testdata/db/db.db" 17 | 18 | Parameters: 19 | - Name: UserId 20 | In: 21 | Kind: cookie 22 | Name: user-id 23 | Required: true 24 | Schema: 25 | DataType: int 26 | -------------------------------------------------------------------------------- /service/reader/testdata/cases/case019_derive_columns/populate_db/datly_acl.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "subject": "Kamil", 5 | "criteria": "ROLE IN ('ADMIN')", 6 | "data_view": "users_accounts" 7 | } 8 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case019_derive_columns/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: datly_acl 5 | Schema: 6 | Name: datly_acl 7 | InheritSchemaColumns: true 8 | Connectors: 9 | - Name: db 10 | Driver: sqlite3 11 | DSN: "./testdata/db/db.db" -------------------------------------------------------------------------------- /service/reader/testdata/cases/case021_on_fetch/populate_other/audiences.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "info": "1,2", 6 | "info2": "" 7 | }, 8 | { 9 | "id": 2, 10 | "info": "", 11 | "info2": "20,30" 12 | } 13 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case021_on_fetch/populate_other/deals.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "deal_id":"", 6 | "name": "deal 1" 7 | }, 8 | { 9 | "id": 2, 10 | "deal_id":"", 11 | "name": "deal 2" 12 | }, 13 | { 14 | "id": 3, 15 | "deal_id":"", 16 | "name": "deal 3" 17 | }, 18 | { 19 | "deal_id": "10", 20 | "id": 4, 21 | "name": "deal 4" 22 | }, 23 | { 24 | "deal_id":"20", 25 | "id": 5, 26 | "name": "deal 5" 27 | }, 28 | { 29 | "deal_id": "30", 30 | "id": 6, 31 | "name": "deal 6" 32 | } 33 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case022_types/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case023_columns_codec/populate_db/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "Id": 1, 5 | "Name": "John,David,Anna", 6 | "Role": "" 7 | } 8 | ] -------------------------------------------------------------------------------- /service/reader/testdata/cases/case023_columns_codec/resources.yaml: -------------------------------------------------------------------------------- 1 | Views: 2 | - Connector: 3 | Ref: db 4 | Name: events 5 | From: "SELECT name FROM users" 6 | ColumnsConfig: 7 | name: 8 | Codec: 9 | Name: Strings 10 | Schema: 11 | DataType: string 12 | Cardinality: Many 13 | 14 | Connectors: 15 | - Name: db 16 | Driver: sqlite3 17 | DSN: "./testdata/db/db.db" 18 | -------------------------------------------------------------------------------- /service/reader/testdata/cases/case024_one_to_one_ns/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/datasets/dataset001_events/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /service/reader/testdata/datasets/dataset001_events/populate_other/event_types.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "name" : "type 1", 6 | "account_id": 33 7 | }, 8 | { 9 | "id": 11, 10 | "name" : "type 2", 11 | "account_id": 33 12 | }, 13 | { 14 | "id": 111, 15 | "name" : "type 3", 16 | "account_id": 36 17 | }, 18 | { 19 | "id": 4, 20 | "name" : "type 4", 21 | "account_id": 36 22 | }, 23 | { 24 | "id": 5, 25 | "name" : "type 5", 26 | "account_id": 37 27 | } 28 | ] -------------------------------------------------------------------------------- /service/reader/testdata/datasets/dataset002_nils/populate_db/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1 5 | } 6 | ] -------------------------------------------------------------------------------- /service/reader/testdata/db_config.yaml: -------------------------------------------------------------------------------- 1 | datastore: db 2 | config: 3 | driverName: sqlite3 4 | descriptor: ./testdata/db/db.db 5 | recreate: true 6 | scripts: 7 | - URL: testdata/db_schema.sql 8 | -------------------------------------------------------------------------------- /service/reader/testdata/other_config.yaml: -------------------------------------------------------------------------------- 1 | datastore: other 2 | config: 3 | driverName: sqlite3 4 | descriptor: ./testdata/db/other.db 5 | recreate: true 6 | scripts: 7 | - URL: testdata/other_schema.sql 8 | -------------------------------------------------------------------------------- /service/reader/time.go: -------------------------------------------------------------------------------- 1 | package reader 2 | 3 | import "time" 4 | 5 | var Now = time.Now 6 | var Diff = func(t1, t2 time.Time) time.Duration { 7 | return t1.Sub(t2) 8 | } 9 | -------------------------------------------------------------------------------- /service/session/reader.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "context" 5 | reader "github.com/viant/datly/service/reader" 6 | "github.com/viant/datly/view" 7 | ) 8 | 9 | func (s *Session) ReadInto(ctx context.Context, dest interface{}, aView *view.View) error { 10 | if err := s.SetViewState(ctx, aView); err != nil { 11 | return err 12 | } 13 | aReader := reader.New() 14 | return aReader.ReadInto(ctx, dest, aView, reader.WithResourceState(s.state)) 15 | } 16 | -------------------------------------------------------------------------------- /service/session/views.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import "sync" 4 | 5 | type views struct { 6 | populatedView map[string]bool 7 | sync.Mutex 8 | } 9 | 10 | func (c *views) canPopulateView(name string) bool { 11 | c.Lock() 12 | defer c.Unlock() 13 | if _, ok := c.populatedView[name]; ok { 14 | return false 15 | } 16 | c.populatedView[name] = true 17 | return true 18 | } 19 | 20 | func newViews() *views { 21 | return &views{populatedView: make(map[string]bool)} 22 | } 23 | -------------------------------------------------------------------------------- /shared/args.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | import "strings" 4 | 5 | func EnsureArgs(query string, args *[]interface{}) { 6 | parameterCount := strings.Count(query, "?") 7 | for i := len(*args); i < parameterCount; i++ { //ensure parameters 8 | *args = append(*args, "") 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /shared/combine.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | import "fmt" 4 | 5 | func CombineErrors(header string, errors []error) error { 6 | if len(errors) == 0 { 7 | return nil 8 | } 9 | 10 | outputErr := fmt.Errorf(header) 11 | for _, err := range errors { 12 | outputErr = fmt.Errorf("%w; %v", outputErr, err.Error()) 13 | } 14 | 15 | return outputErr 16 | } 17 | -------------------------------------------------------------------------------- /shared/const.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | const ( 4 | ExecKindService = "service" 5 | ) 6 | -------------------------------------------------------------------------------- /shared/consts.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | // BuiltInKey represents keys that are provided as parameters for every view.View in view.Session 4 | type BuiltInKey string 5 | 6 | const ( 7 | //DataViewName represents View.DbName parameter 8 | DataViewName BuiltInKey = "session.View.DbName" 9 | //SubjectName represents PrincialSubject parameter 10 | SubjectName BuiltInKey = "session.PrincialSubject" 11 | ) 12 | -------------------------------------------------------------------------------- /shared/deref.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | import "reflect" 4 | 5 | func Elem(rType reflect.Type) reflect.Type { 6 | switch rType.Kind() { 7 | case reflect.Ptr, reflect.Slice: 8 | return Elem(rType.Elem()) 9 | } 10 | return rType 11 | } 12 | -------------------------------------------------------------------------------- /shared/marshaller.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | // Unmarshal converts data to destination, destination has to be a pointer to desired output type 4 | type Unmarshal func(data []byte, destination interface{}) error 5 | 6 | // Marshal converts source to byte array 7 | type Marshal func(src interface{}) ([]byte, error) 8 | -------------------------------------------------------------------------------- /shared/module.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | ) 8 | 9 | func FindModulePath(packagePath string) (string, error) { 10 | currentPath := packagePath 11 | for { 12 | modPath := filepath.Join(currentPath, "go.mod") 13 | if _, err := os.Stat(modPath); err == nil { 14 | return filepath.Rel(currentPath, packagePath) 15 | } 16 | 17 | parent := filepath.Dir(currentPath) 18 | if parent == "/" || parent == "" { 19 | return "", fmt.Errorf("failed to find module path") 20 | } 21 | currentPath = parent 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /shared/not_empty.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | func FirstNotEmpty(values ...string) string { 4 | for _, value := range values { 5 | if value != "" { 6 | return value 7 | } 8 | } 9 | 10 | return "" 11 | } 12 | -------------------------------------------------------------------------------- /shared/path.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | import ( 4 | "net/http" 5 | "strings" 6 | ) 7 | 8 | func ExtractPath(name string) (string, string) { 9 | pair := strings.Split(name, ":") 10 | method := http.MethodGet 11 | URI := "" 12 | switch len(pair) { 13 | case 1: 14 | URI = name 15 | case 2: 16 | method = pair[0] 17 | URI = pair[1] 18 | } 19 | return method, URI 20 | } 21 | -------------------------------------------------------------------------------- /shared/ref.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | //Reference wraps Ref, objects with Reference can be build based on other object of the same type. 4 | type Reference struct { 5 | Ref string `json:",omitempty" yaml:"ref,omitempty"` 6 | } 7 | -------------------------------------------------------------------------------- /shared/text.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | import "strings" 4 | 5 | func TrimPair(text string, begin, end byte) string { 6 | text = strings.TrimSpace(text) 7 | if text == "" { 8 | return text 9 | } 10 | if text[0] == begin { 11 | text = text[1:] 12 | if text[len(text)-1] == end { 13 | text = text[:len(text)-1] 14 | } 15 | } 16 | return text 17 | } 18 | -------------------------------------------------------------------------------- /utils/debug/debug.go: -------------------------------------------------------------------------------- 1 | package debug 2 | 3 | import "os" 4 | 5 | var Enabled = os.Getenv("DATLY_DEBUG") != "" 6 | 7 | func SetEnabled(value bool) { 8 | Enabled = value 9 | } 10 | -------------------------------------------------------------------------------- /utils/formatter/normalize.go: -------------------------------------------------------------------------------- 1 | package formatter 2 | 3 | import ( 4 | "github.com/viant/tagly/format/text" 5 | "strings" 6 | ) 7 | 8 | func NormalizePath(path string) string { 9 | segments := strings.Split(path, ".") 10 | for i, segment := range segments { 11 | segmentFormat := text.DetectCaseFormat(segment) 12 | if !segmentFormat.IsDefined() || segmentFormat == text.CaseFormatUpperCamel { 13 | continue 14 | } 15 | 16 | segments[i] = segmentFormat.Format(segment, text.CaseFormatUpperCamel) 17 | } 18 | return strings.Join(segments, ".") 19 | } 20 | -------------------------------------------------------------------------------- /utils/httputils/compress.go: -------------------------------------------------------------------------------- 1 | package httputils 2 | 3 | import ( 4 | "bytes" 5 | "compress/gzip" 6 | "io" 7 | ) 8 | 9 | // Compress compresses input using gzip 10 | func Compress(reader io.Reader) (*bytes.Buffer, error) { 11 | buffer := new(bytes.Buffer) 12 | writer := gzip.NewWriter(buffer) 13 | _, err := io.Copy(writer, reader) 14 | if err != nil { 15 | return nil, err 16 | } 17 | 18 | _ = writer.Flush() 19 | err = writer.Close() 20 | return buffer, err 21 | } 22 | -------------------------------------------------------------------------------- /utils/types/accessors_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "net/http" 5 | "reflect" 6 | "testing" 7 | ) 8 | 9 | func TestAccessors(t *testing.T) { 10 | testCases := []struct { 11 | description string 12 | namer Namer 13 | rType reflect.Type 14 | }{ 15 | { 16 | description: "cyclic ref", 17 | namer: &VeltyNamer{}, 18 | rType: reflect.TypeOf(&http.Request{}), 19 | }, 20 | } 21 | 22 | for _, testCase := range testCases { 23 | accessor := NewAccessors(testCase.namer) 24 | accessor.Init(testCase.rType) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /utils/types/object.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | var StrErrType = reflect.TypeOf(fmt.Errorf("")) 9 | 10 | func IsObject(anError interface{}) bool { 11 | rType := reflect.TypeOf(anError) 12 | if rType == StrErrType { 13 | return false 14 | } 15 | 16 | for rType.Kind() == reflect.Ptr || rType.Kind() == reflect.Slice { 17 | rType = rType.Elem() 18 | } 19 | 20 | return rType.Kind() == reflect.Struct 21 | } 22 | 23 | func IsMulti(destType reflect.Type) bool { 24 | return destType.Kind() == reflect.Slice || destType.Kind() == reflect.Array 25 | } 26 | -------------------------------------------------------------------------------- /utils/types/reflect.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | func NewValue(p reflect.Type) interface{} { 8 | return newReflectValue(p).Interface() 9 | } 10 | 11 | func newReflectValue(p reflect.Type) reflect.Value { 12 | if p.Kind() == reflect.Ptr { 13 | return reflect.New(p.Elem()) 14 | } 15 | return reflect.New(p).Elem() 16 | } 17 | -------------------------------------------------------------------------------- /view/batch.go: -------------------------------------------------------------------------------- 1 | package view 2 | 3 | type BatchData struct { 4 | ColumnNames []string 5 | Size int 6 | ParentReadSize int 7 | 8 | Values []interface{} //all values from parent 9 | ValuesBatch []interface{} //batched values defined view.Batch.Size 10 | } 11 | 12 | func (b *BatchData) ColIn() []interface{} { 13 | return b.Values 14 | } 15 | 16 | func (b *BatchData) ColInBatch() []interface{} { 17 | return b.ValuesBatch 18 | } 19 | -------------------------------------------------------------------------------- /view/extension/codec/nil.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | import ( 4 | "context" 5 | "github.com/viant/xdatly/codec" 6 | "reflect" 7 | ) 8 | 9 | const ( 10 | KeyNil = "Nil" 11 | ) 12 | 13 | type Nil struct { 14 | } 15 | 16 | func (i *Nil) ResultType(paramType reflect.Type) (reflect.Type, error) { 17 | return paramType, nil 18 | } 19 | 20 | func (i *Nil) Value(ctx context.Context, raw interface{}, options ...codec.Option) (interface{}, error) { 21 | return nil, nil 22 | } 23 | -------------------------------------------------------------------------------- /view/extension/plugin.go: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | import "time" 4 | 5 | const PluginConfig = "Config" 6 | const PackageName = "PackageName" 7 | const TypesName = "Types" 8 | 9 | type Metadata struct { 10 | CreationTime time.Time `json:",omitempty"` 11 | URL string `json:",omitempty"` 12 | Version string `json:",omitempty"` 13 | } 14 | -------------------------------------------------------------------------------- /view/keywords/context.go: -------------------------------------------------------------------------------- 1 | package keywords 2 | 3 | type ( 4 | ContextMetadata struct { 5 | ContextName string 6 | Metadata interface{} 7 | UnexpandRaw bool 8 | } 9 | ) 10 | 11 | func NewContextMetadata(name string, metadata interface{}, unexpandRaw bool) *ContextMetadata { 12 | return &ContextMetadata{ 13 | ContextName: name, 14 | Metadata: metadata, 15 | UnexpandRaw: unexpandRaw, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /view/keywords/fn.go: -------------------------------------------------------------------------------- 1 | package keywords 2 | 3 | type StandaloneFn struct{} 4 | -------------------------------------------------------------------------------- /view/metric.go: -------------------------------------------------------------------------------- 1 | package view 2 | 3 | import ( 4 | "github.com/viant/gmetric" 5 | "reflect" 6 | ) 7 | 8 | // Metrics represents a view metrics 9 | type Metrics struct { 10 | *gmetric.Service 11 | Method string 12 | } 13 | 14 | type metricsLocation struct{} 15 | 16 | func metricLocation() string { 17 | return reflect.TypeOf(metricsLocation{}).PkgPath() 18 | } 19 | -------------------------------------------------------------------------------- /view/names.go: -------------------------------------------------------------------------------- 1 | package view 2 | 3 | import "github.com/viant/datly/shared" 4 | 5 | // Names represents columns names slice. 6 | type Names []string 7 | 8 | // Indexm creates column map. 9 | func (c Names) Index() map[string]bool { 10 | result := make(map[string]bool) 11 | for _, column := range c { 12 | keys := shared.KeysOf(column, true) 13 | for _, key := range keys { 14 | result[key] = true 15 | } 16 | } 17 | return result 18 | } 19 | -------------------------------------------------------------------------------- /view/state/async.go: -------------------------------------------------------------------------------- 1 | package state 2 | 3 | import "strings" 4 | 5 | // IsReservedAsyncState returns true if reserved async state 6 | func IsReservedAsyncState(name string) bool { 7 | isAsync := false 8 | switch strings.ToLower(name) { 9 | case "userid", "useremail", "jobmatchkey": 10 | isAsync = true 11 | } 12 | return isAsync 13 | } 14 | -------------------------------------------------------------------------------- /view/state/cardinality.go: -------------------------------------------------------------------------------- 1 | package state 2 | 3 | type ( 4 | Cardinality string 5 | ) 6 | 7 | const ( 8 | One Cardinality = "One" 9 | Many Cardinality = "Many" 10 | ) 11 | -------------------------------------------------------------------------------- /view/state/handler.go: -------------------------------------------------------------------------------- 1 | package state 2 | 3 | // Handler represents a handler 4 | type Handler struct { 5 | Name string `tag:"name,omitempty"` 6 | Args []string `tag:"arguments,omitempty"` 7 | } 8 | -------------------------------------------------------------------------------- /view/state/hook.go: -------------------------------------------------------------------------------- 1 | package state 2 | 3 | import "context" 4 | 5 | // Initializer is an interface that should be implemented by any type that needs to be initialized 6 | type Initializer interface { 7 | Init(ctx context.Context) error 8 | } 9 | 10 | // Finalizer is an interface that should be implemented by any type that needs to be finalized 11 | type Finalizer interface { 12 | Finalize(ctx context.Context) error 13 | } 14 | -------------------------------------------------------------------------------- /view/state/kind/locator.go: -------------------------------------------------------------------------------- 1 | package kind 2 | 3 | import ( 4 | "context" 5 | "github.com/viant/datly/view/state" 6 | ) 7 | 8 | // Locator defines state locator 9 | type Locator interface { 10 | 11 | //Value returns parameter value 12 | Value(ctx context.Context, name string) (interface{}, bool, error) 13 | 14 | //Names returns names of supported parameters 15 | Names() []string 16 | } 17 | 18 | // KindLocator defines state value kind locators 19 | type KindLocator interface { 20 | Lookup(kind state.Kind) (Locator, error) 21 | } 22 | -------------------------------------------------------------------------------- /view/state/kind/locator/factory.go: -------------------------------------------------------------------------------- 1 | package locator 2 | 3 | import ( 4 | "github.com/viant/datly/view/state/kind" 5 | ) 6 | 7 | // NewLocator new locators 8 | type NewLocator func(options ...Option) (kind.Locator, error) 9 | -------------------------------------------------------------------------------- /view/state/kind/locator/marshaller.go: -------------------------------------------------------------------------------- 1 | package locator 2 | 3 | // Unmarshal converts data into dest 4 | type Unmarshal func([]byte, interface{}) error 5 | -------------------------------------------------------------------------------- /view/state/kind/locator/transient.go: -------------------------------------------------------------------------------- 1 | package locator 2 | 3 | import ( 4 | "context" 5 | "github.com/viant/datly/view/state/kind" 6 | ) 7 | 8 | type Transient struct{} 9 | 10 | func (v *Transient) Names() []string { 11 | return nil 12 | } 13 | 14 | func (v *Transient) Value(ctx context.Context, name string) (interface{}, bool, error) { 15 | if name == "" { 16 | return nil, false, nil 17 | } 18 | return nil, true, nil 19 | } 20 | 21 | // NewTransient returns Transient locator 22 | func NewTransient(_ ...Option) (kind.Locator, error) { 23 | ret := &Transient{} 24 | return ret, nil 25 | } 26 | -------------------------------------------------------------------------------- /view/state/predicate.go: -------------------------------------------------------------------------------- 1 | package state 2 | 3 | import ( 4 | "github.com/viant/datly/view/extension" 5 | "github.com/viant/datly/view/tags" 6 | ) 7 | 8 | func BuildPredicate(aTag *tags.Tag, param *Parameter) { 9 | if aTag == nil || len(aTag.Predicates) == 0 { 10 | return 11 | } 12 | for _, pTag := range aTag.Predicates { 13 | pTag.Init(param.Name) 14 | param.Predicates = append(param.Predicates, &extension.PredicateConfig{ 15 | Group: pTag.Group, 16 | Name: pTag.Name, 17 | Args: pTag.Arguments, 18 | Ensure: pTag.Ensure}) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /view/tags/desription.go: -------------------------------------------------------------------------------- 1 | package tags 2 | 3 | const DescriptionTag = "desc" 4 | const ExampleTag = "example" 5 | -------------------------------------------------------------------------------- /view/tags/testdata/foo.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM FOO -------------------------------------------------------------------------------- /view/template/any.go: -------------------------------------------------------------------------------- 1 | package template 2 | 3 | import "github.com/viant/parsly" 4 | 5 | type AnyMatcher struct { 6 | } 7 | 8 | func NewAnyMatcher() parsly.Matcher { 9 | return &AnyMatcher{} 10 | } 11 | 12 | func (a *AnyMatcher) Match(cursor *parsly.Cursor) (matched int) { 13 | if cursor.Pos < cursor.InputSize { 14 | return 1 15 | } 16 | return 0 17 | } 18 | -------------------------------------------------------------------------------- /view/template/value.go: -------------------------------------------------------------------------------- 1 | package template 2 | 3 | type Value struct { 4 | Key string 5 | Fragment string 6 | } 7 | -------------------------------------------------------------------------------- /view/time.go: -------------------------------------------------------------------------------- 1 | package view 2 | 3 | import "time" 4 | 5 | var Now = time.Now 6 | -------------------------------------------------------------------------------- /warmup/testdata/case001/populate/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | {}, 3 | { 4 | "id": 1, 5 | "event_type_id": 2, 6 | "quantity": 33.23432374000549, 7 | "timestamp": "2019-03-11 02:20:33", 8 | "user_id": 1 9 | }, 10 | { 11 | "id": 10, 12 | "event_type_id": 11, 13 | "quantity": 21.957962334156036, 14 | "timestamp": "2019-03-15 12:07:33", 15 | "user_id": 2 16 | }, 17 | { 18 | "id": 100, 19 | "event_type_id": 111, 20 | "quantity": 5.084940046072006, 21 | "timestamp": "2019-04-10 05:15:33", 22 | "user_id": 3 23 | } 24 | ] -------------------------------------------------------------------------------- /warmup/testdata/db_config.yaml: -------------------------------------------------------------------------------- 1 | datastore: db 2 | config: 3 | driverName: sqlite3 4 | descriptor: ./testdata/db/db.db 5 | recreate: true 6 | scripts: 7 | - URL: testdata/db_schema.sql 8 | -------------------------------------------------------------------------------- /warmup/testdata/db_schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS events; 2 | CREATE TABLE events 3 | ( 4 | id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 5 | timestamp DATETIME, 6 | event_type_id INTEGER, 7 | quantity DECIMAL(7, 2) DEFAULT NULL, 8 | user_id INTEGER 9 | ); 10 | 11 | DROP TABLE IF EXISTS event_types; 12 | CREATE TABLE event_types 13 | ( 14 | id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 15 | type text, 16 | code text 17 | ); 18 | --------------------------------------------------------------------------------