From 0bd2df91a123336c2c95f0894d9488cebfffacda Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Mon, 31 Jul 2023 23:00:02 +0800 Subject: [PATCH] Resolve conflicts among master branch and develop branch (#5286) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feature extend readthrough for cache module (#5116) * feature 增加readthrough * feature: add write though for cache mode (#5117) * feature: add writethough for cache mode * feature add singleflight cache (#5119) * build(deps): bump go.opentelemetry.io/otel/trace from 1.8.0 to 1.11.2 Bumps [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) from 1.8.0 to 1.11.2. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.8.0...v1.11.2) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/trace dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix 5129: must set formatter after init the logger * remove beego.vip * build(deps): bump actions/stale from 5 to 7 Bumps [actions/stale](https://github.com/actions/stale) from 5 to 7. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v5...v7) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * fix 5079: only log msg when the channel is not closed (#5132) * optimize test * upgrade otel dependencies to v1.11.2 * format code * Bloom filter cache (#5126) * feature: add bloom filter cache * feature upload remove all temp file * bugfix Controller SaveToFile remove all temp file * rft: motify BeeLogger signalChan (#5139) * add non-block write log in asynchronous mode (#5150) * add non-block write log in asynchronous mode --------- Co-authored-by: chenhaokun * fix the docsite URL (#5173) * Unified gopkg.in/yaml version to v2 (#5169) * Unified gopkg.in/yaml version to v2 and go mod tidy * update CHANGELOG * bugfix: protect field access with lock to avoid possible data race (#5211) * fix some comments (#5194) Signed-off-by: cui fliter * build(deps): bump github.com/prometheus/client_golang (#5213) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.14.0 to 1.15.1. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.14.0...v1.15.1) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump go.etcd.io/etcd/client/v3 from 3.5.4 to 3.5.9 (#5209) Bumps [go.etcd.io/etcd/client/v3](https://github.com/etcd-io/etcd) from 3.5.4 to 3.5.9. - [Release notes](https://github.com/etcd-io/etcd/releases) - [Commits](https://github.com/etcd-io/etcd/compare/v3.5.4...v3.5.9) --- updated-dependencies: - dependency-name: go.etcd.io/etcd/client/v3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * cache: fix typo and optimize the naming * Release 2.1.0 change log * bugfix: beegoAppConfig String and Strings function has bug * httplib: fix unstable test, do not use httplib.org * chore: pkg imported more than once * chore: fmt modify * chore: Use github.com/go-kit/log * chore: unnecessary use of fmt.Sprintf * fix: golangci-lint error * orm: refactor ORM introducing internal/models pkg * remove adapter package * build(deps): bump github.com/bits-and-blooms/bloom/v3 Bumps [github.com/bits-and-blooms/bloom/v3](https://github.com/bits-and-blooms/bloom) from 3.3.1 to 3.5.0. - [Release notes](https://github.com/bits-and-blooms/bloom/releases) - [Commits](https://github.com/bits-and-blooms/bloom/compare/v3.3.1...v3.5.0) --- updated-dependencies: - dependency-name: github.com/bits-and-blooms/bloom/v3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * feat: add write-delete cache mode * fix: unnecessary assignment to the blank identifier * fix: add change into .CHANGELOG file * build(deps): bump golang.org/x/sync from 0.1.0 to 0.3.0 Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.1.0 to 0.3.0. - [Commits](https://github.com/golang/sync/compare/v0.1.0...v0.3.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * build(deps): bump golang.org/x/crypto Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.0.0-20220315160706-3147a52a75dd to 0.10.0. - [Commits](https://github.com/golang/crypto/commits/v0.10.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * remove golang--lint-ci * Beego web.Run() runs the server twice * fix 5255: Check the rows.Err() if rows.Next() is false * closes 5254: %COL% should be a common placeholder * build(deps): bump github.com/prometheus/client_golang Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.15.1 to 1.16.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.15.1...v1.16.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix: use of ioutil package (#5261) * fix ioutil.NopCloser * fix ioutil.ReadAll * fix ioutil.ReadFile * fix ioutil.WriteFile * run goimports -w -format-only ./ * update CHANGELOG.md * feature: add write-double-delete cache mode (#5263) * cache/redis: support skipEmptyPrefix option (#5264) * fix: refactor InsertValue method (#5267) * fix: refactor insertValue method and add the test * fix: exec goimports and add Licence file header * fix: modify construct method of dbBase * fix: add modify record into CHANGELOG * fix: modify InsertOrUpdate method (#5269) * fix: modify InsertOrUpdate method, Remove the isMulti variable and its associated code * fix: Delete unnecessary judgment branches * fix: add modify record into CHANGELOG * cache/redis: use redisConfig to receive incoming JSON (previously using a map) (#5268) * refactor cache/redis: Use redisConfig to receive incoming JSON (previously using a map). * refactor cache/redis: Use the string type to receive JSON parameters. --------- Co-authored-by: Tan * fix: refactor Delete method (#5271) * fix: refactor Delete method and add test * fix: add modify record into CHANGELOG * fix: refactor update sql (#5274) * fix: refactor UpdateSQL method and add test * fix: add modify record into CHANGELOG * fix: modify url in the CHANGELOG * fix: modify pr url in the CHANGELOG * Fix setPK function for table without primary key (#5276) --------- Signed-off-by: dependabot[bot] Signed-off-by: cui fliter Co-authored-by: Stone-afk <73482944+Stone-afk@users.noreply.github.com> Co-authored-by: hookokoko Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: hookokoko <648646891@qq.com> Co-authored-by: Stone-afk <1711865140@qq.com> Co-authored-by: chenhaokun Co-authored-by: Xuing Co-authored-by: cui fliter Co-authored-by: guoguangwu Co-authored-by: uzziah Co-authored-by: Hanjiang Yu Co-authored-by: Kota Co-authored-by: Uzziah <120019273+uzziahlin@users.noreply.github.com> Co-authored-by: Handkerchiefs-t <59816423+Handkerchiefs-t@users.noreply.github.com> Co-authored-by: Tan Co-authored-by: mlgd --- .github/linters/.golangci.yml | 43 -- .github/workflows/golangci-lint.yml | 32 - CHANGELOG.md | 31 + LICENSE | 2 +- README.md | 2 + adapter/admin.go | 45 -- adapter/app.go | 260 ------- adapter/beego.go | 74 -- adapter/build_info.go | 27 - adapter/cache/cache.go | 102 --- adapter/cache/cache_adapter.go | 117 --- adapter/cache/cache_test.go | 142 ---- adapter/cache/conv.go | 44 -- adapter/cache/conv_test.go | 143 ---- adapter/cache/file.go | 30 - adapter/cache/memcache/memcache.go | 43 -- adapter/cache/memcache/memcache_test.go | 84 --- adapter/cache/memory.go | 28 - adapter/cache/redis/redis.go | 46 -- adapter/cache/redis/redis_test.go | 121 --- adapter/cache/ssdb/ssdb.go | 15 - adapter/cache/ssdb/ssdb_test.go | 77 -- adapter/config.go | 177 ----- adapter/config/adapter.go | 191 ----- adapter/config/config.go | 150 ---- adapter/config/config_test.go | 53 -- adapter/config/env/env.go | 50 -- adapter/config/env/env_test.go | 75 -- adapter/config/fake.go | 25 - adapter/config/ini_test.go | 188 ----- adapter/config/json_test.go | 207 ----- adapter/config/xml/xml.go | 33 - adapter/config/xml/xml_test.go | 125 ---- adapter/config/yaml/yaml.go | 33 - adapter/config/yaml/yaml_test.go | 114 --- adapter/context/acceptencoder.go | 45 -- adapter/context/context.go | 145 ---- adapter/context/input.go | 282 ------- adapter/context/output.go | 154 ---- adapter/context/param/conv.go | 18 - adapter/context/param/conv_test.go | 39 - adapter/context/param/methodparams.go | 29 - adapter/context/param/methodparams_test.go | 34 - adapter/context/param/options.go | 45 -- adapter/context/renderer.go | 8 - adapter/context/response.go | 26 - adapter/controller.go | 401 ---------- adapter/doc.go | 16 - adapter/error.go | 201 ----- adapter/filter.go | 36 - adapter/flash.go | 63 -- adapter/fs.go | 35 - adapter/grace/grace.go | 94 --- adapter/grace/server.go | 48 -- adapter/httplib/httplib.go | 282 ------- adapter/httplib/httplib_test.go | 290 -------- adapter/log.go | 127 ---- adapter/logs/accesslog.go | 27 - adapter/logs/alils/alils.go | 5 - adapter/logs/es/es.go | 5 - adapter/logs/log.go | 346 --------- adapter/logs/log_adapter.go | 43 -- adapter/logs/logger.go | 38 - adapter/logs/logger_test.go | 24 - adapter/metric/prometheus.go | 100 --- adapter/metric/prometheus_test.go | 45 -- adapter/migration/ddl.go | 198 ----- adapter/migration/doc.go | 32 - adapter/migration/migration.go | 111 --- adapter/namespace.go | 396 ---------- adapter/orm/cmd.go | 28 - adapter/orm/db.go | 22 - adapter/orm/db_alias.go | 121 --- adapter/orm/models.go | 25 - adapter/orm/models_boot.go | 40 - adapter/orm/models_boot_test.go | 31 - adapter/orm/orm.go | 314 -------- adapter/orm/orm_conds.go | 83 --- adapter/orm/orm_queryset.go | 32 - adapter/orm/qb.go | 27 - adapter/orm/qb_mysql.go | 150 ---- adapter/orm/qb_tidb.go | 147 ---- adapter/orm/types.go | 150 ---- adapter/orm/utils.go | 286 ------- adapter/orm/utils_test.go | 66 -- adapter/plugins/apiauth/apiauth.go | 94 --- adapter/plugins/apiauth/apiauth_test.go | 20 - adapter/plugins/auth/basic.go | 81 -- adapter/plugins/authz/authz.go | 80 -- adapter/plugins/authz/authz_model.conf | 14 - adapter/plugins/authz/authz_policy.csv | 7 - adapter/plugins/authz/authz_test.go | 123 --- adapter/plugins/cors/cors.go | 70 -- adapter/policy.go | 57 -- adapter/router.go | 281 ------- adapter/session/couchbase/sess_couchbase.go | 117 --- adapter/session/ledis/ledis_session.go | 86 --- adapter/session/memcache/sess_memcache.go | 116 --- adapter/session/mysql/sess_mysql.go | 133 ---- adapter/session/postgres/sess_postgresql.go | 137 ---- adapter/session/provider_adapter.go | 104 --- adapter/session/redis/sess_redis.go | 119 --- .../session/redis_cluster/redis_cluster.go | 119 --- .../redis_sentinel/sess_redis_sentinel.go | 120 --- .../sess_redis_sentinel_test.go | 75 -- adapter/session/sess_cookie.go | 114 --- adapter/session/sess_cookie_test.go | 108 --- adapter/session/sess_file.go | 106 --- adapter/session/sess_file_test.go | 336 --------- adapter/session/sess_mem.go | 106 --- adapter/session/sess_mem_test.go | 58 -- adapter/session/sess_test.go | 51 -- adapter/session/sess_utils.go | 29 - adapter/session/session.go | 165 ---- adapter/session/ssdb/sess_ssdb.go | 83 --- adapter/session/store_adapter.go | 84 --- adapter/swagger/swagger.go | 68 -- adapter/template.go | 108 --- adapter/templatefunc.go | 149 ---- adapter/templatefunc_test.go | 236 ------ adapter/testing/client.go | 45 -- adapter/toolbox/healthcheck.go | 51 -- adapter/toolbox/profile.go | 41 - adapter/toolbox/profile_test.go | 28 - adapter/toolbox/statistics.go | 50 -- adapter/toolbox/statistics_test.go | 43 -- adapter/toolbox/task.go | 294 -------- adapter/tree.go | 48 -- adapter/utils/caller.go | 24 - adapter/utils/caller_test.go | 28 - adapter/utils/captcha/LICENSE | 19 - adapter/utils/captcha/README.md | 45 -- adapter/utils/captcha/captcha.go | 121 --- adapter/utils/captcha/image.go | 35 - adapter/utils/captcha/image_test.go | 58 -- adapter/utils/debug.go | 34 - adapter/utils/debug_test.go | 46 -- adapter/utils/file.go | 47 -- adapter/utils/mail.go | 63 -- adapter/utils/mail_test.go | 41 - adapter/utils/pagination/controller.go | 26 - adapter/utils/pagination/doc.go | 54 -- adapter/utils/pagination/paginator.go | 112 --- adapter/utils/rand.go | 24 - adapter/utils/rand_test.go | 33 - adapter/utils/safemap.go | 58 -- adapter/utils/safemap_test.go | 89 --- adapter/utils/slice.go | 102 --- adapter/utils/slice_test.go | 29 - adapter/utils/utils.go | 10 - adapter/validation/util.go | 60 -- adapter/validation/validation.go | 273 ------- adapter/validation/validation_test.go | 504 ------------- adapter/validation/validators.go | 512 ------------- client/cache/bloom_filter_cache_test.go | 3 +- client/cache/cache.go | 6 +- client/cache/error_code.go | 4 + client/cache/file.go | 5 +- client/cache/memcache/memcache.go | 9 +- client/cache/redis/redis.go | 159 ++-- client/cache/redis/redis_test.go | 111 +++ client/cache/write_delete.go | 96 +++ client/cache/write_delete_test.go | 393 ++++++++++ client/httplib/client_option_test.go | 261 ------- client/httplib/filter/opentracing/filter.go | 2 +- client/httplib/http_response.go | 4 +- client/httplib/httpclient.go | 5 +- client/httplib/httpclient_test.go | 272 ++++--- client/httplib/httplib.go | 30 +- client/httplib/httplib_test.go | 310 ++++---- client/orm/cmd.go | 34 +- client/orm/cmd_utils.go | 47 +- client/orm/cmd_utils_test.go | 39 + client/orm/db.go | 549 ++++++++------ client/orm/db_alias.go | 8 +- client/orm/db_mysql.go | 38 +- client/orm/db_oracle.go | 14 +- client/orm/db_postgres.go | 26 +- client/orm/db_sqlite.go | 20 +- client/orm/db_tables.go | 116 +-- client/orm/db_test.go | 231 ++++++ client/orm/db_tidb.go | 4 +- client/orm/db_utils.go | 60 +- client/orm/filter.go | 4 +- client/orm/filter_orm_decorator.go | 10 +- .../orm/internal/buffers/buffers.go | 30 +- client/orm/internal/logs/log.go | 20 + .../orm/internal/models}/models_fields.go | 430 +++++++---- .../{ => internal/models}/models_info_f.go | 306 ++++---- client/orm/internal/models/models_info_m.go | 148 ++++ .../orm/{ => internal/models}/models_utils.go | 118 ++- .../models/models_utils_test.go} | 52 +- .../orm/internal/models/types.go | 14 +- client/orm/internal/utils/utils.go | 249 +++++++ client/orm/invocation.go | 10 +- client/orm/migration/ddl.go | 8 +- client/orm/mock/mock_orm.go | 6 +- client/orm/model_utils_test.go | 8 +- client/orm/models.go | 315 ++++---- client/orm/models_fields.go | 704 ++---------------- client/orm/models_info_m.go | 148 ---- client/orm/models_test.go | 6 +- client/orm/models_utils_test.go | 35 - client/orm/orm.go | 110 +-- client/orm/orm_log.go | 19 +- client/orm/orm_object.go | 20 +- client/orm/orm_querym2m.go | 45 +- client/orm/orm_queryset.go | 48 +- client/orm/orm_raw.go | 102 +-- client/orm/orm_test.go | 46 +- client/orm/qb_mysql.go | 6 +- client/orm/qb_postgres.go | 6 +- client/orm/types.go | 243 +++--- client/orm/utils.go | 302 +------- core/admin/healthcheck.go | 15 +- core/config/config.go | 41 +- core/config/env/env.go | 3 +- core/config/env/env_test.go | 2 +- core/config/ini.go | 3 +- core/config/ini_test.go | 3 +- core/config/json/json.go | 8 +- core/config/toml/toml.go | 3 +- core/config/xml/xml.go | 20 +- core/config/yaml/yaml.go | 13 +- core/logs/alils/log.pb.go | 11 +- core/logs/alils/log_project.go | 42 +- core/logs/alils/log_store.go | 10 +- core/logs/alils/machine_group.go | 4 +- core/logs/es/es.go | 2 +- core/logs/file.go | 19 +- core/logs/file_test.go | 5 +- core/logs/smtp.go | 1 + core/utils/mail.go | 4 +- core/utils/pagination/doc.go | 74 +- core/utils/pagination/paginator.go | 10 +- core/validation/util.go | 16 +- core/validation/validation.go | 1 - core/validation/validators.go | 41 +- go.mod | 21 +- go.sum | 39 +- server/web/admin.go | 7 +- server/web/beego.go | 3 +- server/web/captcha/captcha.go | 45 +- server/web/config.go | 4 +- server/web/context/context.go | 1 - server/web/context/input.go | 7 +- server/web/controller.go | 42 +- server/web/controller_test.go | 3 +- server/web/doc.go | 1 - server/web/error.go | 6 +- server/web/filter.go | 4 +- server/web/filter/apiauth/apiauth.go | 8 +- server/web/filter/auth/basic.go | 2 +- server/web/filter/authz/authz.go | 2 +- server/web/filter/cors/cors.go | 4 +- server/web/filter/opentracing/filter.go | 2 +- server/web/grace/grace.go | 36 +- server/web/grace/server.go | 3 +- server/web/namespace.go | 53 +- server/web/server.go | 3 +- server/web/session/sess_file.go | 8 +- server/web/session/session.go | 13 +- server/web/staticfile.go | 4 +- server/web/staticfile_test.go | 9 +- server/web/template.go | 5 +- server/web/templatefunc.go | 39 +- task/task.go | 14 +- task/task_test.go | 2 +- test/bindata.go | 12 +- 269 files changed, 3904 insertions(+), 18313 deletions(-) delete mode 100644 .github/linters/.golangci.yml delete mode 100644 .github/workflows/golangci-lint.yml delete mode 100644 adapter/admin.go delete mode 100644 adapter/app.go delete mode 100644 adapter/beego.go delete mode 100644 adapter/build_info.go delete mode 100644 adapter/cache/cache.go delete mode 100644 adapter/cache/cache_adapter.go delete mode 100644 adapter/cache/cache_test.go delete mode 100644 adapter/cache/conv.go delete mode 100644 adapter/cache/conv_test.go delete mode 100644 adapter/cache/file.go delete mode 100644 adapter/cache/memcache/memcache.go delete mode 100644 adapter/cache/memcache/memcache_test.go delete mode 100644 adapter/cache/memory.go delete mode 100644 adapter/cache/redis/redis.go delete mode 100644 adapter/cache/redis/redis_test.go delete mode 100644 adapter/cache/ssdb/ssdb.go delete mode 100644 adapter/cache/ssdb/ssdb_test.go delete mode 100644 adapter/config.go delete mode 100644 adapter/config/adapter.go delete mode 100644 adapter/config/config.go delete mode 100644 adapter/config/config_test.go delete mode 100644 adapter/config/env/env.go delete mode 100644 adapter/config/env/env_test.go delete mode 100644 adapter/config/fake.go delete mode 100644 adapter/config/ini_test.go delete mode 100644 adapter/config/json_test.go delete mode 100644 adapter/config/xml/xml.go delete mode 100644 adapter/config/xml/xml_test.go delete mode 100644 adapter/config/yaml/yaml.go delete mode 100644 adapter/config/yaml/yaml_test.go delete mode 100644 adapter/context/acceptencoder.go delete mode 100644 adapter/context/context.go delete mode 100644 adapter/context/input.go delete mode 100644 adapter/context/output.go delete mode 100644 adapter/context/param/conv.go delete mode 100644 adapter/context/param/conv_test.go delete mode 100644 adapter/context/param/methodparams.go delete mode 100644 adapter/context/param/methodparams_test.go delete mode 100644 adapter/context/param/options.go delete mode 100644 adapter/context/renderer.go delete mode 100644 adapter/context/response.go delete mode 100644 adapter/controller.go delete mode 100644 adapter/doc.go delete mode 100644 adapter/error.go delete mode 100644 adapter/filter.go delete mode 100644 adapter/flash.go delete mode 100644 adapter/fs.go delete mode 100644 adapter/grace/grace.go delete mode 100644 adapter/grace/server.go delete mode 100644 adapter/httplib/httplib.go delete mode 100644 adapter/httplib/httplib_test.go delete mode 100644 adapter/log.go delete mode 100644 adapter/logs/accesslog.go delete mode 100644 adapter/logs/alils/alils.go delete mode 100644 adapter/logs/es/es.go delete mode 100644 adapter/logs/log.go delete mode 100644 adapter/logs/log_adapter.go delete mode 100644 adapter/logs/logger.go delete mode 100644 adapter/logs/logger_test.go delete mode 100644 adapter/metric/prometheus.go delete mode 100644 adapter/metric/prometheus_test.go delete mode 100644 adapter/migration/ddl.go delete mode 100644 adapter/migration/doc.go delete mode 100644 adapter/migration/migration.go delete mode 100644 adapter/namespace.go delete mode 100644 adapter/orm/cmd.go delete mode 100644 adapter/orm/db.go delete mode 100644 adapter/orm/db_alias.go delete mode 100644 adapter/orm/models.go delete mode 100644 adapter/orm/models_boot.go delete mode 100644 adapter/orm/models_boot_test.go delete mode 100644 adapter/orm/orm.go delete mode 100644 adapter/orm/orm_conds.go delete mode 100644 adapter/orm/orm_queryset.go delete mode 100644 adapter/orm/qb.go delete mode 100644 adapter/orm/qb_mysql.go delete mode 100644 adapter/orm/qb_tidb.go delete mode 100644 adapter/orm/types.go delete mode 100644 adapter/orm/utils.go delete mode 100644 adapter/orm/utils_test.go delete mode 100644 adapter/plugins/apiauth/apiauth.go delete mode 100644 adapter/plugins/apiauth/apiauth_test.go delete mode 100644 adapter/plugins/auth/basic.go delete mode 100644 adapter/plugins/authz/authz.go delete mode 100644 adapter/plugins/authz/authz_model.conf delete mode 100644 adapter/plugins/authz/authz_policy.csv delete mode 100644 adapter/plugins/authz/authz_test.go delete mode 100644 adapter/plugins/cors/cors.go delete mode 100644 adapter/policy.go delete mode 100644 adapter/router.go delete mode 100644 adapter/session/couchbase/sess_couchbase.go delete mode 100644 adapter/session/ledis/ledis_session.go delete mode 100644 adapter/session/memcache/sess_memcache.go delete mode 100644 adapter/session/mysql/sess_mysql.go delete mode 100644 adapter/session/postgres/sess_postgresql.go delete mode 100644 adapter/session/provider_adapter.go delete mode 100644 adapter/session/redis/sess_redis.go delete mode 100644 adapter/session/redis_cluster/redis_cluster.go delete mode 100644 adapter/session/redis_sentinel/sess_redis_sentinel.go delete mode 100644 adapter/session/redis_sentinel/sess_redis_sentinel_test.go delete mode 100644 adapter/session/sess_cookie.go delete mode 100644 adapter/session/sess_cookie_test.go delete mode 100644 adapter/session/sess_file.go delete mode 100644 adapter/session/sess_file_test.go delete mode 100644 adapter/session/sess_mem.go delete mode 100644 adapter/session/sess_mem_test.go delete mode 100644 adapter/session/sess_test.go delete mode 100644 adapter/session/sess_utils.go delete mode 100644 adapter/session/session.go delete mode 100644 adapter/session/ssdb/sess_ssdb.go delete mode 100644 adapter/session/store_adapter.go delete mode 100644 adapter/swagger/swagger.go delete mode 100644 adapter/template.go delete mode 100644 adapter/templatefunc.go delete mode 100644 adapter/templatefunc_test.go delete mode 100644 adapter/testing/client.go delete mode 100644 adapter/toolbox/healthcheck.go delete mode 100644 adapter/toolbox/profile.go delete mode 100644 adapter/toolbox/profile_test.go delete mode 100644 adapter/toolbox/statistics.go delete mode 100644 adapter/toolbox/statistics_test.go delete mode 100644 adapter/toolbox/task.go delete mode 100644 adapter/tree.go delete mode 100644 adapter/utils/caller.go delete mode 100644 adapter/utils/caller_test.go delete mode 100644 adapter/utils/captcha/LICENSE delete mode 100644 adapter/utils/captcha/README.md delete mode 100644 adapter/utils/captcha/captcha.go delete mode 100644 adapter/utils/captcha/image.go delete mode 100644 adapter/utils/captcha/image_test.go delete mode 100644 adapter/utils/debug.go delete mode 100644 adapter/utils/debug_test.go delete mode 100644 adapter/utils/file.go delete mode 100644 adapter/utils/mail.go delete mode 100644 adapter/utils/mail_test.go delete mode 100644 adapter/utils/pagination/controller.go delete mode 100644 adapter/utils/pagination/doc.go delete mode 100644 adapter/utils/pagination/paginator.go delete mode 100644 adapter/utils/rand.go delete mode 100644 adapter/utils/rand_test.go delete mode 100644 adapter/utils/safemap.go delete mode 100644 adapter/utils/safemap_test.go delete mode 100644 adapter/utils/slice.go delete mode 100644 adapter/utils/slice_test.go delete mode 100644 adapter/utils/utils.go delete mode 100644 adapter/validation/util.go delete mode 100644 adapter/validation/validation.go delete mode 100644 adapter/validation/validation_test.go delete mode 100644 adapter/validation/validators.go create mode 100644 client/cache/write_delete.go create mode 100644 client/cache/write_delete_test.go delete mode 100644 client/httplib/client_option_test.go create mode 100644 client/orm/cmd_utils_test.go create mode 100644 client/orm/db_test.go rename adapter/orm/orm_log.go => client/orm/internal/buffers/buffers.go (63%) create mode 100644 client/orm/internal/logs/log.go rename {adapter/orm => client/orm/internal/models}/models_fields.go (65%) rename client/orm/{ => internal/models}/models_info_f.go (60%) create mode 100644 client/orm/internal/models/models_info_m.go rename client/orm/{ => internal/models}/models_utils.go (67%) rename client/orm/{utils_test.go => internal/models/models_utils_test.go} (75%) rename adapter/config/json.go => client/orm/internal/models/types.go (73%) create mode 100644 client/orm/internal/utils/utils.go delete mode 100644 client/orm/models_info_m.go delete mode 100644 client/orm/models_utils_test.go diff --git a/.github/linters/.golangci.yml b/.github/linters/.golangci.yml deleted file mode 100644 index baa6098e..00000000 --- a/.github/linters/.golangci.yml +++ /dev/null @@ -1,43 +0,0 @@ -run: - timeout: 5m - skip-files: - - generated.* - -issues: - new: true - -linters: - enable: - - asciicheck - - bodyclose - - deadcode - - depguard - - gci - - gocritic - - gofmt - - gofumpt - - goimports - - goprintffuncname - - gosimple - - govet - - ineffassign - - misspell - - nilerr - - rowserrcheck - - staticcheck - - structcheck - - stylecheck - - typecheck - - unconvert - - unused - - unparam - - varcheck - - whitespace - disable: - - errcheck - -linters-settings: - gci: - local-prefixes: github.com/beego - goimports: - local-prefixes: github.com/beego diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml deleted file mode 100644 index 6e5f0122..00000000 --- a/.github/workflows/golangci-lint.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: golangci-lint -on: - push: - branches: - - master - paths: - - "**/*.go" - - ".github/workflows/golangci-lint.yml" - pull_request: - types: [opened, synchronize, reopened] - paths: - - "**/*.go" - - ".github/workflows/golangci-lint.yml" -permissions: - contents: read - -jobs: - lint: - permissions: - contents: read # for actions/checkout to fetch code - pull-requests: read # for golangci/golangci-lint-action to fetch pull requests - runs-on: ubuntu-latest - steps: - - name: Checkout codebase - uses: actions/checkout@v2 - - - name: golangci-lint - uses: golangci/golangci-lint-action@v2 - with: - version: latest - args: --config=.github/linters/.golangci.yml - only-new-issues: true diff --git a/CHANGELOG.md b/CHANGELOG.md index a749b7be..9c702ff0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,35 @@ # developing +- [httplib: fix unstable unit test which use the httplib.org](https://github.com/beego/beego/pull/5232) +- [rft: remove adapter package](https://github.com/beego/beego/pull/5239) +- [feat: add write-delete cache mode](https://github.com/beego/beego/pull/5242) +- [feat: add write-double-delete cache mode](https://github.com/beego/beego/pull/5243) +- [fix 5255: Check the rows.Err() if rows.Next() is false](https://github.com/beego/beego/pull/5256) +- [orm: missing handling %COL% placeholder](https://github.com/beego/beego/pull/5257) +- [fix: use of ioutil package](https://github.com/beego/beego/pull/5261) +- [cache/redis: support skipEmptyPrefix option ](https://github.com/beego/beego/pull/5264) +- [fix: refactor InsertValue method](https://github.com/beego/beego/pull/5267) +- [fix: modify InsertOrUpdate method, Remove the isMulti variable and its associated code](https://github.com/beego/beego/pull/5269) +- [refactor cache/redis: Use redisConfig to receive incoming JSON (previously using a map)](https://github.com/beego/beego/pull/5268) +- [fix: refactor DeleteSQL method](https://github.com/beego/beego/pull/5271) +- [fix: refactor UpdateSQL method](https://github.com/beego/beego/pull/5274) + +## ORM refactoring +- [introducing internal/models pkg](https://github.com/beego/beego/pull/5238) + +# v2.1.0 +- [unified gopkg.in/yaml version to v2](https://github.com/beego/beego/pull/5169) +- [add non-block write log in asynchronous mode](https://github.com/beego/beego/pull/5150) +- [Fix 5126: support bloom filter cache](https://github.com/beego/beego/pull/5126) +- [Fix 5117: support write though cache](https://github.com/beego/beego/pull/5117) +- [add read through for cache module](https://github.com/beego/beego/pull/5116) +- [add singleflight cache for cache module](https://github.com/beego/beego/pull/5119) +- [Fix 5129: must set formatter after init the logger](https://github.com/beego/beego/pull/5130) +- [Fix 5079: only log msg when the channel is not closed](https://github.com/beego/beego/pull/5132) +- [Fix 4435: Controller SaveToFile remove all temp file](https://github.com/beego/beego/pull/5138) +- [Fix 5079: Split signalChan into flushChan and closeChan](https://github.com/beego/beego/pull/5139) +- [Fix 5172: protect field access with lock to avoid possible data race](https://github.com/beego/beego/pull/5210) +- [cache: fix typo and optimize the naming]() +- [Fix 5176: beegoAppConfig String and Strings function has bug](https://github.com/beego/beego/pull/5211) # v2.1.0 - [unified gopkg.in/yaml version to v2](https://github.com/beego/beego/pull/5169) diff --git a/LICENSE b/LICENSE index 26050108..b947dac3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2014 astaxie +Copyright 2014 Beego Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 1d22455b..36480f82 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Beego is composed of four parts: **Please use RELEASE version, or master branch which contains the latest bug fix** +**We will remove the adapter package in v2.2.0 which will be released in Aug 2023** + ## Quick Start [Old Doc - github](https://github.com/beego/beedoc) diff --git a/adapter/admin.go b/adapter/admin.go deleted file mode 100644 index 527cb201..00000000 --- a/adapter/admin.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "time" - - _ "github.com/beego/beego/v2/core/admin" - "github.com/beego/beego/v2/server/web" -) - -// FilterMonitorFunc is default monitor filter when admin module is enable. -// if this func returns, admin module records qps for this request by condition of this function logic. -// usage: -// func MyFilterMonitor(method, requestPath string, t time.Duration, pattern string, statusCode int) bool { -// if method == "POST" { -// return false -// } -// if t.Nanoseconds() < 100 { -// return false -// } -// if strings.HasPrefix(requestPath, "/astaxie") { -// return false -// } -// return true -// } -// beego.FilterMonitorFunc = MyFilterMonitor. -var FilterMonitorFunc func(string, string, time.Duration, string, int) bool - -// PrintTree prints all registered routers. -func PrintTree() M { - return (M)(web.BeeApp.PrintTree()) -} diff --git a/adapter/app.go b/adapter/app.go deleted file mode 100644 index aaf85a17..00000000 --- a/adapter/app.go +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "net/http" - - context2 "github.com/beego/beego/v2/adapter/context" - "github.com/beego/beego/v2/server/web" - "github.com/beego/beego/v2/server/web/context" -) - -// BeeApp is an application instance -var BeeApp *App - -func init() { - // create beego application - BeeApp = (*App)(web.BeeApp) -} - -// App defines beego application with a new PatternServeMux. -type App web.HttpServer - -// NewApp returns a new beego application. -func NewApp() *App { - return (*App)(web.NewHttpSever()) -} - -// MiddleWare function for http.Handler -type MiddleWare web.MiddleWare - -// Run beego application. -func (app *App) Run(mws ...MiddleWare) { - newMws := oldMiddlewareToNew(mws) - (*web.HttpServer)(app).Run("", newMws...) -} - -func oldMiddlewareToNew(mws []MiddleWare) []web.MiddleWare { - newMws := make([]web.MiddleWare, 0, len(mws)) - for _, old := range mws { - newMws = append(newMws, (web.MiddleWare)(old)) - } - return newMws -} - -// Router adds a patterned controller handler to BeeApp. -// it's an alias method of HttpServer.Router. -// usage: -// simple router -// beego.Router("/admin", &admin.UserController{}) -// beego.Router("/admin/index", &admin.ArticleController{}) -// -// regex router -// -// beego.Router("/api/:id([0-9]+)", &controllers.RController{}) -// -// custom rules -// beego.Router("/api/list",&RestController{},"*:ListFood") -// beego.Router("/api/create",&RestController{},"post:CreateFood") -// beego.Router("/api/update",&RestController{},"put:UpdateFood") -// beego.Router("/api/delete",&RestController{},"delete:DeleteFood") -func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *App { - return (*App)(web.Router(rootpath, c, mappingMethods...)) -} - -// UnregisterFixedRoute unregisters the route with the specified fixedRoute. It is particularly useful -// in web applications that inherit most routes from a base webapp via the underscore -// import, and aim to overwrite only certain paths. -// The method parameter can be empty or "*" for all HTTP methods, or a particular -// method type (e.g. "GET" or "POST") for selective removal. -// -// Usage (replace "GET" with "*" for all methods): -// beego.UnregisterFixedRoute("/yourpreviouspath", "GET") -// beego.Router("/yourpreviouspath", yourControllerAddress, "get:GetNewPage") -func UnregisterFixedRoute(fixedRoute string, method string) *App { - return (*App)(web.UnregisterFixedRoute(fixedRoute, method)) -} - -// Include will generate router file in the router/xxx.go from the controller's comments -// usage: -// beego.Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{}) -// type BankAccount struct{ -// beego.Controller -// } -// -// register the function -// func (b *BankAccount)Mapping(){ -// b.Mapping("ShowAccount" , b.ShowAccount) -// b.Mapping("ModifyAccount", b.ModifyAccount) -// } -// -// //@router /account/:id [get] -// func (b *BankAccount) ShowAccount(){ -// //logic -// } -// -// -// //@router /account/:id [post] -// func (b *BankAccount) ModifyAccount(){ -// //logic -// } -// -// the comments @router url methodlist -// url support all the function Router's pattern -// methodlist [get post head put delete options *] -func Include(cList ...ControllerInterface) *App { - newList := oldToNewCtrlIntfs(cList) - return (*App)(web.Include(newList...)) -} - -func oldToNewCtrlIntfs(cList []ControllerInterface) []web.ControllerInterface { - newList := make([]web.ControllerInterface, 0, len(cList)) - for _, c := range cList { - newList = append(newList, c) - } - return newList -} - -// RESTRouter adds a restful controller handler to BeeApp. -// its' controller implements beego.ControllerInterface and -// defines a param "pattern/:objectId" to visit each resource. -func RESTRouter(rootpath string, c ControllerInterface) *App { - return (*App)(web.RESTRouter(rootpath, c)) -} - -// AutoRouter adds defined controller handler to BeeApp. -// it's same to HttpServer.AutoRouter. -// if beego.AddAuto(&MainController{}) and MainController has methods List and Page, -// visit the url /main/list to exec List function or /main/page to exec Page function. -func AutoRouter(c ControllerInterface) *App { - return (*App)(web.AutoRouter(c)) -} - -// AutoPrefix adds controller handler to BeeApp with prefix. -// it's same to HttpServer.AutoRouterWithPrefix. -// if beego.AutoPrefix("/admin",&MainController{}) and MainController has methods List and Page, -// visit the url /admin/main/list to exec List function or /admin/main/page to exec Page function. -func AutoPrefix(prefix string, c ControllerInterface) *App { - return (*App)(web.AutoPrefix(prefix, c)) -} - -// Get used to register router for Get method -// usage: -// beego.Get("/", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func Get(rootpath string, f FilterFunc) *App { - return (*App)(web.Get(rootpath, func(ctx *context.Context) { - f((*context2.Context)(ctx)) - })) -} - -// Post used to register router for Post method -// usage: -// beego.Post("/api", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func Post(rootpath string, f FilterFunc) *App { - return (*App)(web.Post(rootpath, func(ctx *context.Context) { - f((*context2.Context)(ctx)) - })) -} - -// Delete used to register router for Delete method -// usage: -// beego.Delete("/api", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func Delete(rootpath string, f FilterFunc) *App { - return (*App)(web.Delete(rootpath, func(ctx *context.Context) { - f((*context2.Context)(ctx)) - })) -} - -// Put used to register router for Put method -// usage: -// beego.Put("/api", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func Put(rootpath string, f FilterFunc) *App { - return (*App)(web.Put(rootpath, func(ctx *context.Context) { - f((*context2.Context)(ctx)) - })) -} - -// Head used to register router for Head method -// usage: -// beego.Head("/api", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func Head(rootpath string, f FilterFunc) *App { - return (*App)(web.Head(rootpath, func(ctx *context.Context) { - f((*context2.Context)(ctx)) - })) -} - -// Options used to register router for Options method -// usage: -// beego.Options("/api", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func Options(rootpath string, f FilterFunc) *App { - return (*App)(web.Options(rootpath, func(ctx *context.Context) { - f((*context2.Context)(ctx)) - })) -} - -// Patch used to register router for Patch method -// usage: -// beego.Patch("/api", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func Patch(rootpath string, f FilterFunc) *App { - return (*App)(web.Patch(rootpath, func(ctx *context.Context) { - f((*context2.Context)(ctx)) - })) -} - -// Any used to register router for all methods -// usage: -// beego.Any("/api", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func Any(rootpath string, f FilterFunc) *App { - return (*App)(web.Any(rootpath, func(ctx *context.Context) { - f((*context2.Context)(ctx)) - })) -} - -// Handler used to register a Handler router -// usage: -// beego.Handler("/api", http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) { -// fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) -// })) -func Handler(rootpath string, h http.Handler, options ...interface{}) *App { - return (*App)(web.Handler(rootpath, h, options...)) -} - -// InsertFilter adds a FilterFunc with pattern condition and action constant. -// The pos means action constant including -// beego.BeforeStatic, beego.BeforeRouter, beego.BeforeExec, beego.AfterExec and beego.FinishRouter. -// The bool params is for setting the returnOnOutput value (false allows multiple filters to execute) -func InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) *App { - opts := oldToNewFilterOpts(params) - return (*App)(web.InsertFilter(pattern, pos, func(ctx *context.Context) { - filter((*context2.Context)(ctx)) - }, opts...)) -} diff --git a/adapter/beego.go b/adapter/beego.go deleted file mode 100644 index 0c914241..00000000 --- a/adapter/beego.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "github.com/beego/beego/v2" - "github.com/beego/beego/v2/server/web" -) - -const ( - - // VERSION represent beego web framework version. - VERSION = beego.VERSION - - // DEV is for develop - DEV = web.DEV - // PROD is for production - PROD = web.PROD -) - -// M is Map shortcut -type M web.M - -// Hook function to run -type hookfunc func() error - -// AddAPPStartHook is used to register the hookfunc -// The hookfuncs will run in beego.Run() -// such as initiating session , starting middleware , building template, starting admin control and so on. -func AddAPPStartHook(hf ...hookfunc) { - for i := 0; i < len(hf); i++ { - f := hf[i] - web.AddAPPStartHook(func() error { - return f() - }) - } -} - -// Run beego application. -// beego.Run() default run on HttpPort -// beego.Run("localhost") -// beego.Run(":8089") -// beego.Run("127.0.0.1:8089") -func Run(params ...string) { - web.Run(params...) -} - -// RunWithMiddleWares Run beego application with middlewares. -func RunWithMiddleWares(addr string, mws ...MiddleWare) { - newMws := oldMiddlewareToNew(mws) - web.RunWithMiddleWares(addr, newMws...) -} - -// TestBeegoInit is for test package init -func TestBeegoInit(ap string) { - web.TestBeegoInit(ap) -} - -// InitBeegoBeforeTest is for test package init -func InitBeegoBeforeTest(appConfigPath string) { - web.InitBeegoBeforeTest(appConfigPath) -} diff --git a/adapter/build_info.go b/adapter/build_info.go deleted file mode 100644 index 1e8dacf0..00000000 --- a/adapter/build_info.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2020 astaxie -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -var ( - BuildVersion string - BuildGitRevision string - BuildStatus string - BuildTag string - BuildTime string - - GoVersion string - - GitBranch string -) diff --git a/adapter/cache/cache.go b/adapter/cache/cache.go deleted file mode 100644 index 9e3abfd3..00000000 --- a/adapter/cache/cache.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package cache provide a Cache interface and some implement engine -// Usage: -// -// import( -// "github.com/beego/beego/v2/client/cache" -// ) -// -// bm, err := cache.NewCache("memory", `{"interval":60}`) -// -// Use it like this: -// -// bm.Put("astaxie", 1, 10 * time.Second) -// bm.Get("astaxie") -// bm.IsExist("astaxie") -// bm.Delete("astaxie") -// -package cache - -import ( - "fmt" - "time" -) - -// Cache interface contains all behaviors for cache adapter. -// usage: -// cache.Register("file",cache.NewFileCache) // this operation is run in init method of file.go. -// c,err := cache.NewCache("file","{....}") -// c.Put("key",value, 3600 * time.Second) -// v := c.Get("key") -// -// c.Incr("counter") // now is 1 -// c.Incr("counter") // now is 2 -// count := c.Get("counter").(int) -type Cache interface { - // Get will get cached value by key. - Get(key string) interface{} - // GetMulti is a batch version of Get. - GetMulti(keys []string) []interface{} - // Put will set cached value with key and expire time. - Put(key string, val interface{}, timeout time.Duration) error - // Delete will delete cached value by key. - Delete(key string) error - // Incr will increase cached int value by key, as a counter. - Incr(key string) error - // Decr will decrease cached int value by key, as a counter. - Decr(key string) error - // IsExist can check if cached value exists or not. - IsExist(key string) bool - // ClearAll will clear all cache. - ClearAll() error - // StartAndGC will start gc routine based on config string settings. - StartAndGC(config string) error -} - -// Instance is a function create a new Cache Instance -type Instance func() Cache - -var adapters = make(map[string]Instance) - -// Register makes a cache adapter available by the adapter name. -// If Register is called twice with the same name or if driver is nil, -// it panics. -func Register(name string, adapter Instance) { - if adapter == nil { - panic("cache: Register adapter is nil") - } - if _, ok := adapters[name]; ok { - panic("cache: Register called twice for adapter " + name) - } - adapters[name] = adapter -} - -// NewCache Create a new cache driver by adapter name and config string. -// config need to be correct JSON as string: {"interval":360}. -// it will start gc automatically. -func NewCache(adapterName, config string) (adapter Cache, err error) { - instanceFunc, ok := adapters[adapterName] - if !ok { - err = fmt.Errorf("cache: unknown adapter name %q (forgot to import?)", adapterName) - return - } - adapter = instanceFunc() - err = adapter.StartAndGC(config) - if err != nil { - adapter = nil - } - return -} diff --git a/adapter/cache/cache_adapter.go b/adapter/cache/cache_adapter.go deleted file mode 100644 index cc46cad7..00000000 --- a/adapter/cache/cache_adapter.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2020 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cache - -import ( - "context" - "time" - - "github.com/beego/beego/v2/client/cache" -) - -type newToOldCacheAdapter struct { - delegate cache.Cache -} - -func (c *newToOldCacheAdapter) Get(key string) interface{} { - res, _ := c.delegate.Get(context.Background(), key) - return res -} - -func (c *newToOldCacheAdapter) GetMulti(keys []string) []interface{} { - res, _ := c.delegate.GetMulti(context.Background(), keys) - return res -} - -func (c *newToOldCacheAdapter) Put(key string, val interface{}, timeout time.Duration) error { - return c.delegate.Put(context.Background(), key, val, timeout) -} - -func (c *newToOldCacheAdapter) Delete(key string) error { - return c.delegate.Delete(context.Background(), key) -} - -func (c *newToOldCacheAdapter) Incr(key string) error { - return c.delegate.Incr(context.Background(), key) -} - -func (c *newToOldCacheAdapter) Decr(key string) error { - return c.delegate.Decr(context.Background(), key) -} - -func (c *newToOldCacheAdapter) IsExist(key string) bool { - res, err := c.delegate.IsExist(context.Background(), key) - return res && err == nil -} - -func (c *newToOldCacheAdapter) ClearAll() error { - return c.delegate.ClearAll(context.Background()) -} - -func (c *newToOldCacheAdapter) StartAndGC(config string) error { - return c.delegate.StartAndGC(config) -} - -func CreateNewToOldCacheAdapter(delegate cache.Cache) Cache { - return &newToOldCacheAdapter{ - delegate: delegate, - } -} - -type oldToNewCacheAdapter struct { - old Cache -} - -func (o *oldToNewCacheAdapter) Get(ctx context.Context, key string) (interface{}, error) { - return o.old.Get(key), nil -} - -func (o *oldToNewCacheAdapter) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) { - return o.old.GetMulti(keys), nil -} - -func (o *oldToNewCacheAdapter) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error { - return o.old.Put(key, val, timeout) -} - -func (o *oldToNewCacheAdapter) Delete(ctx context.Context, key string) error { - return o.old.Delete(key) -} - -func (o *oldToNewCacheAdapter) Incr(ctx context.Context, key string) error { - return o.old.Incr(key) -} - -func (o *oldToNewCacheAdapter) Decr(ctx context.Context, key string) error { - return o.old.Decr(key) -} - -func (o *oldToNewCacheAdapter) IsExist(ctx context.Context, key string) (bool, error) { - return o.old.IsExist(key), nil -} - -func (o *oldToNewCacheAdapter) ClearAll(ctx context.Context) error { - return o.old.ClearAll() -} - -func (o *oldToNewCacheAdapter) StartAndGC(config string) error { - return o.old.StartAndGC(config) -} - -func CreateOldToNewAdapter(old Cache) cache.Cache { - return &oldToNewCacheAdapter{ - old: old, - } -} diff --git a/adapter/cache/cache_test.go b/adapter/cache/cache_test.go deleted file mode 100644 index bdb7e41f..00000000 --- a/adapter/cache/cache_test.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cache - -import ( - "os" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -const initError = "init err" - -func TestCacheIncr(t *testing.T) { - bm, err := NewCache("memory", `{"interval":20}`) - if err != nil { - t.Error(initError) - } - // timeoutDuration := 10 * time.Second - - bm.Put("edwardhey", 0, time.Second*20) - wg := sync.WaitGroup{} - wg.Add(10) - for i := 0; i < 10; i++ { - go func() { - defer wg.Done() - bm.Incr("edwardhey") - }() - } - wg.Wait() - if bm.Get("edwardhey").(int) != 10 { - t.Error("Incr err") - } -} - -func TestCache(t *testing.T) { - bm, err := NewCache("memory", `{"interval":20}`) - - assert.Nil(t, err) - - timeoutDuration := 5 * time.Second - err = bm.Put("astaxie", 1, timeoutDuration) - assert.Nil(t, err) - - assert.True(t, bm.IsExist("astaxie")) - - assert.Equal(t, 1, bm.Get("astaxie")) - - time.Sleep(10 * time.Second) - - assert.False(t, bm.IsExist("astaxie")) - - err = bm.Put("astaxie", 1, timeoutDuration) - assert.Nil(t, err) - - err = bm.Incr("astaxie") - assert.Nil(t, err) - - assert.Equal(t, 2, bm.Get("astaxie")) - - assert.Nil(t, bm.Decr("astaxie")) - - assert.Equal(t, 1, bm.Get("astaxie")) - - assert.Nil(t, bm.Delete("astaxie")) - - assert.False(t, bm.IsExist("astaxie")) - - assert.Nil(t, bm.Put("astaxie", "author", timeoutDuration)) - - assert.True(t, bm.IsExist("astaxie")) - - assert.Equal(t, "author", bm.Get("astaxie")) - - assert.Nil(t, bm.Put("astaxie1", "author1", timeoutDuration)) - - assert.True(t, bm.IsExist("astaxie1")) - - vv := bm.GetMulti([]string{"astaxie", "astaxie1"}) - - assert.Equal(t, 2, len(vv)) - - assert.Equal(t, "author", vv[0]) - - assert.Equal(t, "author1", vv[1]) -} - -func TestFileCache(t *testing.T) { - bm, err := NewCache("file", `{"CachePath":"cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}`) - - assert.Nil(t, err) - timeoutDuration := 5 * time.Second - - assert.Nil(t, bm.Put("astaxie", 1, timeoutDuration)) - - assert.True(t, bm.IsExist("astaxie")) - - assert.Equal(t, 1, bm.Get("astaxie")) - - assert.Nil(t, bm.Incr("astaxie")) - - assert.Equal(t, 2, bm.Get("astaxie")) - - assert.Nil(t, bm.Decr("astaxie")) - - assert.Equal(t, 1, bm.Get("astaxie")) - assert.Nil(t, bm.Delete("astaxie")) - - assert.False(t, bm.IsExist("astaxie")) - - assert.Nil(t, bm.Put("astaxie", "author", timeoutDuration)) - - assert.True(t, bm.IsExist("astaxie")) - - assert.Equal(t, "author", bm.Get("astaxie")) - - assert.Nil(t, bm.Put("astaxie1", "author1", timeoutDuration)) - - assert.True(t, bm.IsExist("astaxie1")) - - vv := bm.GetMulti([]string{"astaxie", "astaxie1"}) - - assert.Equal(t, 2, len(vv)) - - assert.Equal(t, "author", vv[0]) - assert.Equal(t, "author1", vv[1]) - assert.Nil(t, os.RemoveAll("cache")) -} diff --git a/adapter/cache/conv.go b/adapter/cache/conv.go deleted file mode 100644 index 052c4f3b..00000000 --- a/adapter/cache/conv.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cache - -import ( - "github.com/beego/beego/v2/client/cache" -) - -// GetString convert interface to string. -func GetString(v interface{}) string { - return cache.GetString(v) -} - -// GetInt convert interface to int. -func GetInt(v interface{}) int { - return cache.GetInt(v) -} - -// GetInt64 convert interface to int64. -func GetInt64(v interface{}) int64 { - return cache.GetInt64(v) -} - -// GetFloat64 convert interface to float64. -func GetFloat64(v interface{}) float64 { - return cache.GetFloat64(v) -} - -// GetBool convert interface to bool. -func GetBool(v interface{}) bool { - return cache.GetBool(v) -} diff --git a/adapter/cache/conv_test.go b/adapter/cache/conv_test.go deleted file mode 100644 index af49e92c..00000000 --- a/adapter/cache/conv_test.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cache - -import ( - "testing" -) - -func TestGetString(t *testing.T) { - t1 := "test1" - if "test1" != GetString(t1) { - t.Error("get string from string error") - } - t2 := []byte("test2") - if "test2" != GetString(t2) { - t.Error("get string from byte array error") - } - t3 := 1 - if "1" != GetString(t3) { - t.Error("get string from int error") - } - var t4 int64 = 1 - if "1" != GetString(t4) { - t.Error("get string from int64 error") - } - t5 := 1.1 - if "1.1" != GetString(t5) { - t.Error("get string from float64 error") - } - - if "" != GetString(nil) { - t.Error("get string from nil error") - } -} - -func TestGetInt(t *testing.T) { - t1 := 1 - if 1 != GetInt(t1) { - t.Error("get int from int error") - } - var t2 int32 = 32 - if 32 != GetInt(t2) { - t.Error("get int from int32 error") - } - var t3 int64 = 64 - if 64 != GetInt(t3) { - t.Error("get int from int64 error") - } - t4 := "128" - if 128 != GetInt(t4) { - t.Error("get int from num string error") - } - if 0 != GetInt(nil) { - t.Error("get int from nil error") - } -} - -func TestGetInt64(t *testing.T) { - var i int64 = 1 - t1 := 1 - if i != GetInt64(t1) { - t.Error("get int64 from int error") - } - var t2 int32 = 1 - if i != GetInt64(t2) { - t.Error("get int64 from int32 error") - } - var t3 int64 = 1 - if i != GetInt64(t3) { - t.Error("get int64 from int64 error") - } - t4 := "1" - if i != GetInt64(t4) { - t.Error("get int64 from num string error") - } - if 0 != GetInt64(nil) { - t.Error("get int64 from nil") - } -} - -func TestGetFloat64(t *testing.T) { - f := 1.11 - var t1 float32 = 1.11 - if f != GetFloat64(t1) { - t.Error("get float64 from float32 error") - } - t2 := 1.11 - if f != GetFloat64(t2) { - t.Error("get float64 from float64 error") - } - t3 := "1.11" - if f != GetFloat64(t3) { - t.Error("get float64 from string error") - } - - var f2 float64 = 1 - t4 := 1 - if f2 != GetFloat64(t4) { - t.Error("get float64 from int error") - } - - if 0 != GetFloat64(nil) { - t.Error("get float64 from nil error") - } -} - -func TestGetBool(t *testing.T) { - t1 := true - if !GetBool(t1) { - t.Error("get bool from bool error") - } - t2 := "true" - if !GetBool(t2) { - t.Error("get bool from string error") - } - if GetBool(nil) { - t.Error("get bool from nil error") - } -} - -func byteArrayEquals(a []byte, b []byte) bool { - if len(a) != len(b) { - return false - } - for i, v := range a { - if v != b[i] { - return false - } - } - return true -} diff --git a/adapter/cache/file.go b/adapter/cache/file.go deleted file mode 100644 index b010a031..00000000 --- a/adapter/cache/file.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cache - -import ( - "github.com/beego/beego/v2/client/cache" -) - -// NewFileCache Create new file cache with no config. -// the level and expiry need set in method StartAndGC as config string. -func NewFileCache() Cache { - // return &FileCache{CachePath:FileCachePath, FileSuffix:FileCacheFileSuffix} - return CreateNewToOldCacheAdapter(cache.NewFileCache()) -} - -func init() { - Register("file", NewFileCache) -} diff --git a/adapter/cache/memcache/memcache.go b/adapter/cache/memcache/memcache.go deleted file mode 100644 index 180e8e15..00000000 --- a/adapter/cache/memcache/memcache.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package memcache for cache provider -// -// depend on github.com/bradfitz/gomemcache/memcache -// -// go install github.com/bradfitz/gomemcache/memcache -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/client/cache/memcache" -// "github.com/beego/beego/v2/client/cache" -// ) -// -// bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`) -// -package memcache - -import ( - "github.com/beego/beego/v2/adapter/cache" - "github.com/beego/beego/v2/client/cache/memcache" -) - -// NewMemCache create new memcache adapter. -func NewMemCache() cache.Cache { - return cache.CreateNewToOldCacheAdapter(memcache.NewMemCache()) -} - -func init() { - cache.Register("memcache", NewMemCache) -} diff --git a/adapter/cache/memcache/memcache_test.go b/adapter/cache/memcache/memcache_test.go deleted file mode 100644 index 13663907..00000000 --- a/adapter/cache/memcache/memcache_test.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package memcache - -import ( - "fmt" - "os" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/beego/beego/v2/adapter/cache" -) - -func TestMemcacheCache(t *testing.T) { - addr := os.Getenv("MEMCACHE_ADDR") - if addr == "" { - addr = "127.0.0.1:11211" - } - - bm, err := cache.NewCache("memcache", fmt.Sprintf(`{"conn": "%s"}`, addr)) - assert.Nil(t, err) - timeoutDuration := 5 * time.Second - - assert.Nil(t, bm.Put("astaxie", "1", timeoutDuration)) - - assert.True(t, bm.IsExist("astaxie")) - - time.Sleep(11 * time.Second) - - assert.False(t, bm.IsExist("astaxie")) - - assert.Nil(t, bm.Put("astaxie", "1", timeoutDuration)) - v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))) - assert.Nil(t, err) - assert.Equal(t, 1, v) - - assert.Nil(t, bm.Incr("astaxie")) - - v, err = strconv.Atoi(string(bm.Get("astaxie").([]byte))) - assert.Nil(t, err) - assert.Equal(t, 2, v) - - assert.Nil(t, bm.Decr("astaxie")) - - v, err = strconv.Atoi(string(bm.Get("astaxie").([]byte))) - assert.Nil(t, err) - assert.Equal(t, 1, v) - - assert.Nil(t, bm.Delete("astaxie")) - - assert.False(t, bm.IsExist("astaxie")) - - assert.Nil(t, bm.Put("astaxie", "author", timeoutDuration)) - - assert.True(t, bm.IsExist("astaxie")) - - assert.Equal(t, []byte("author"), bm.Get("astaxie")) - - assert.Nil(t, bm.Put("astaxie1", "author1", timeoutDuration)) - - assert.True(t, bm.IsExist("astaxie1")) - - vv := bm.GetMulti([]string{"astaxie", "astaxie1"}) - assert.Equal(t, 2, len(vv)) - assert.Equal(t, []byte("author"), vv[0]) - assert.Equal(t, []byte("author1"), vv[1]) - - assert.Nil(t, bm.ClearAll()) -} diff --git a/adapter/cache/memory.go b/adapter/cache/memory.go deleted file mode 100644 index dfb80aa4..00000000 --- a/adapter/cache/memory.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cache - -import ( - "github.com/beego/beego/v2/client/cache" -) - -// NewMemoryCache returns a new MemoryCache. -func NewMemoryCache() Cache { - return CreateNewToOldCacheAdapter(cache.NewMemoryCache()) -} - -func init() { - Register("memory", NewMemoryCache) -} diff --git a/adapter/cache/redis/redis.go b/adapter/cache/redis/redis.go deleted file mode 100644 index 7c7bff80..00000000 --- a/adapter/cache/redis/redis.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package redis for cache provider -// -// depend on github.com/gomodule/redigo/redis -// -// go install github.com/gomodule/redigo/redis -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/client/cache/redis" -// "github.com/beego/beego/v2/client/cache" -// ) -// -// bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`) -// -package redis - -import ( - "github.com/beego/beego/v2/adapter/cache" - redis2 "github.com/beego/beego/v2/client/cache/redis" -) - -// DefaultKey the collection name of redis for cache adapter. -var DefaultKey = "beecacheRedis" - -// NewRedisCache create new redis cache with default collection name. -func NewRedisCache() cache.Cache { - return cache.CreateNewToOldCacheAdapter(redis2.NewRedisCache()) -} - -func init() { - cache.Register("redis", NewRedisCache) -} diff --git a/adapter/cache/redis/redis_test.go b/adapter/cache/redis/redis_test.go deleted file mode 100644 index a4200fab..00000000 --- a/adapter/cache/redis/redis_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package redis - -import ( - "fmt" - "os" - "testing" - "time" - - "github.com/gomodule/redigo/redis" - "github.com/stretchr/testify/assert" - - "github.com/beego/beego/v2/adapter/cache" -) - -const ( - initError = "init err" - setError = "set Error" -) - -func TestRedisCache(t *testing.T) { - redisAddr := os.Getenv("REDIS_ADDR") - if redisAddr == "" { - redisAddr = "127.0.0.1:6379" - } - - bm, err := cache.NewCache("redis", fmt.Sprintf(`{"conn": "%s"}`, redisAddr)) - assert.Nil(t, err) - timeoutDuration := 5 * time.Second - - assert.Nil(t, bm.Put("astaxie", 1, timeoutDuration)) - - assert.True(t, bm.IsExist("astaxie")) - - time.Sleep(7 * time.Second) - - assert.False(t, bm.IsExist("astaxie")) - - assert.Nil(t, bm.Put("astaxie", 1, timeoutDuration)) - - v, err := redis.Int(bm.Get("astaxie"), err) - assert.Nil(t, err) - assert.Equal(t, 1, v) - - assert.Nil(t, bm.Incr("astaxie")) - - v, err = redis.Int(bm.Get("astaxie"), err) - assert.Nil(t, err) - assert.Equal(t, 2, v) - - assert.Nil(t, bm.Decr("astaxie")) - - v, err = redis.Int(bm.Get("astaxie"), err) - assert.Nil(t, err) - assert.Equal(t, 1, v) - - assert.Nil(t, bm.Delete("astaxie")) - - assert.False(t, bm.IsExist("astaxie")) - - assert.Nil(t, bm.Put("astaxie", "author", timeoutDuration)) - assert.True(t, bm.IsExist("astaxie")) - - vs, err := redis.String(bm.Get("astaxie"), err) - assert.Nil(t, err) - assert.Equal(t, "author", vs) - - assert.Nil(t, bm.Put("astaxie1", "author1", timeoutDuration)) - - assert.True(t, bm.IsExist("astaxie1")) - - vv := bm.GetMulti([]string{"astaxie", "astaxie1"}) - - assert.Equal(t, 2, len(vv)) - - vs, err = redis.String(vv[0], nil) - - assert.Nil(t, err) - assert.Equal(t, "author", vs) - - vs, err = redis.String(vv[1], nil) - - assert.Nil(t, err) - assert.Equal(t, "author1", vs) - - assert.Nil(t, bm.ClearAll()) - // test clear all -} - -func TestCacheScan(t *testing.T) { - timeoutDuration := 10 * time.Second - // init - bm, err := cache.NewCache("redis", `{"conn": "127.0.0.1:6379"}`) - if err != nil { - t.Error(initError) - } - // insert all - for i := 0; i < 10000; i++ { - if err = bm.Put(fmt.Sprintf("astaxie%d", i), fmt.Sprintf("author%d", i), timeoutDuration); err != nil { - t.Error(setError, err) - } - } - - // clear all - if err = bm.ClearAll(); err != nil { - t.Error("clear all err") - } -} diff --git a/adapter/cache/ssdb/ssdb.go b/adapter/cache/ssdb/ssdb.go deleted file mode 100644 index 8f6e50d3..00000000 --- a/adapter/cache/ssdb/ssdb.go +++ /dev/null @@ -1,15 +0,0 @@ -package ssdb - -import ( - "github.com/beego/beego/v2/adapter/cache" - ssdb2 "github.com/beego/beego/v2/client/cache/ssdb" -) - -// NewSsdbCache create new ssdb adapter. -func NewSsdbCache() cache.Cache { - return cache.CreateNewToOldCacheAdapter(ssdb2.NewSsdbCache()) -} - -func init() { - cache.Register("ssdb", NewSsdbCache) -} diff --git a/adapter/cache/ssdb/ssdb_test.go b/adapter/cache/ssdb/ssdb_test.go deleted file mode 100644 index 9f00e5c7..00000000 --- a/adapter/cache/ssdb/ssdb_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package ssdb - -import ( - "fmt" - "os" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/beego/beego/v2/adapter/cache" -) - -func TestSsdbcacheCache(t *testing.T) { - ssdbAddr := os.Getenv("SSDB_ADDR") - if ssdbAddr == "" { - ssdbAddr = "127.0.0.1:8888" - } - - ssdb, err := cache.NewCache("ssdb", fmt.Sprintf(`{"conn": "%s"}`, ssdbAddr)) - - assert.Nil(t, err) - - assert.False(t, ssdb.IsExist("ssdb")) - // test put and exist - timeoutDuration := 3 * time.Second - // timeoutDuration := -10*time.Second if timeoutDuration is negtive,it means permanent - assert.Nil(t, ssdb.Put("ssdb", "ssdb", timeoutDuration)) - assert.True(t, ssdb.IsExist("ssdb")) - - assert.Nil(t, ssdb.Put("ssdb", "ssdb", timeoutDuration)) - - assert.Equal(t, "ssdb", ssdb.Get("ssdb")) - - // inc/dec test done - assert.Nil(t, ssdb.Put("ssdb", "2", timeoutDuration)) - - assert.Nil(t, ssdb.Incr("ssdb")) - - v, err := strconv.Atoi(ssdb.Get("ssdb").(string)) - assert.Nil(t, err) - assert.Equal(t, 3, v) - - assert.Nil(t, ssdb.Decr("ssdb")) - - assert.Nil(t, ssdb.Put("ssdb", "3", timeoutDuration)) - - // test del - v, err = strconv.Atoi(ssdb.Get("ssdb").(string)) - assert.Nil(t, err) - assert.Equal(t, 3, v) - - assert.Nil(t, ssdb.Delete("ssdb")) - assert.False(t, ssdb.IsExist("ssdb")) - - // test string - assert.Nil(t, ssdb.Put("ssdb", "ssdb", -10*time.Second)) - - assert.True(t, ssdb.IsExist("ssdb")) - assert.Equal(t, "ssdb", ssdb.Get("ssdb")) - - // test GetMulti done - assert.Nil(t, ssdb.Put("ssdb1", "ssdb1", -10*time.Second)) - assert.True(t, ssdb.IsExist("ssdb1")) - - vv := ssdb.GetMulti([]string{"ssdb", "ssdb1"}) - assert.Equal(t, 2, len(vv)) - - assert.Equal(t, "ssdb", vv[0]) - assert.Equal(t, "ssdb1", vv[1]) - - assert.Nil(t, ssdb.ClearAll()) - assert.False(t, ssdb.IsExist("ssdb")) - assert.False(t, ssdb.IsExist("ssdb1")) - // test clear all done -} diff --git a/adapter/config.go b/adapter/config.go deleted file mode 100644 index 36e0a9c4..00000000 --- a/adapter/config.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "github.com/beego/beego/v2/adapter/session" - newCfg "github.com/beego/beego/v2/core/config" - "github.com/beego/beego/v2/server/web" -) - -// Config is the main struct for BConfig -type Config web.Config - -// Listen holds for http and https related config -type Listen web.Listen - -// WebConfig holds web related config -type WebConfig web.WebConfig - -// SessionConfig holds session related config -type SessionConfig web.SessionConfig - -// LogConfig holds Log related config -type LogConfig web.LogConfig - -var ( - // BConfig is the default config for Application - BConfig *Config - // AppConfig is the instance of Config, store the config information from file - AppConfig *beegoAppConfig - // AppPath is the absolute path to the app - AppPath string - // GlobalSessions is the instance for the session manager - GlobalSessions *session.Manager - - // appConfigPath is the path to the config files - appConfigPath string - // appConfigProvider is the provider for the config, default is ini - appConfigProvider = "ini" - // WorkPath is the absolute path to project root directory - WorkPath string -) - -func init() { - BConfig = (*Config)(web.BConfig) - AppPath = web.AppPath - - WorkPath = web.WorkPath - - AppConfig = &beegoAppConfig{innerConfig: (newCfg.Configer)(web.AppConfig)} -} - -// LoadAppConfig allow developer to apply a config file -func LoadAppConfig(adapterName, configPath string) error { - return web.LoadAppConfig(adapterName, configPath) -} - -type beegoAppConfig struct { - innerConfig newCfg.Configer -} - -func (b *beegoAppConfig) Set(key, val string) error { - if err := b.innerConfig.Set(BConfig.RunMode+"::"+key, val); err != nil { - return b.innerConfig.Set(key, val) - } - return nil -} - -func (b *beegoAppConfig) String(key string) string { - if v, err := b.innerConfig.String(BConfig.RunMode + "::" + key); v != "" && err != nil { - return v - } - res, _ := b.innerConfig.String(key) - return res -} - -func (b *beegoAppConfig) Strings(key string) []string { - if v, err := b.innerConfig.Strings(BConfig.RunMode + "::" + key); len(v) > 0 && err != nil { - return v - } - res, _ := b.innerConfig.Strings(key) - return res -} - -func (b *beegoAppConfig) Int(key string) (int, error) { - if v, err := b.innerConfig.Int(BConfig.RunMode + "::" + key); err == nil { - return v, nil - } - return b.innerConfig.Int(key) -} - -func (b *beegoAppConfig) Int64(key string) (int64, error) { - if v, err := b.innerConfig.Int64(BConfig.RunMode + "::" + key); err == nil { - return v, nil - } - return b.innerConfig.Int64(key) -} - -func (b *beegoAppConfig) Bool(key string) (bool, error) { - if v, err := b.innerConfig.Bool(BConfig.RunMode + "::" + key); err == nil { - return v, nil - } - return b.innerConfig.Bool(key) -} - -func (b *beegoAppConfig) Float(key string) (float64, error) { - if v, err := b.innerConfig.Float(BConfig.RunMode + "::" + key); err == nil { - return v, nil - } - return b.innerConfig.Float(key) -} - -func (b *beegoAppConfig) DefaultString(key string, defaultVal string) string { - if v := b.String(key); v != "" { - return v - } - return defaultVal -} - -func (b *beegoAppConfig) DefaultStrings(key string, defaultVal []string) []string { - if v := b.Strings(key); len(v) != 0 { - return v - } - return defaultVal -} - -func (b *beegoAppConfig) DefaultInt(key string, defaultVal int) int { - if v, err := b.Int(key); err == nil { - return v - } - return defaultVal -} - -func (b *beegoAppConfig) DefaultInt64(key string, defaultVal int64) int64 { - if v, err := b.Int64(key); err == nil { - return v - } - return defaultVal -} - -func (b *beegoAppConfig) DefaultBool(key string, defaultVal bool) bool { - if v, err := b.Bool(key); err == nil { - return v - } - return defaultVal -} - -func (b *beegoAppConfig) DefaultFloat(key string, defaultVal float64) float64 { - if v, err := b.Float(key); err == nil { - return v - } - return defaultVal -} - -func (b *beegoAppConfig) DIY(key string) (interface{}, error) { - return b.innerConfig.DIY(key) -} - -func (b *beegoAppConfig) GetSection(section string) (map[string]string, error) { - return b.innerConfig.GetSection(section) -} - -func (b *beegoAppConfig) SaveConfigFile(filename string) error { - return b.innerConfig.SaveConfigFile(filename) -} diff --git a/adapter/config/adapter.go b/adapter/config/adapter.go deleted file mode 100644 index f7cfcb19..00000000 --- a/adapter/config/adapter.go +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2020 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package config - -import ( - "github.com/pkg/errors" - - "github.com/beego/beego/v2/core/config" -) - -type newToOldConfigerAdapter struct { - delegate config.Configer -} - -func (c *newToOldConfigerAdapter) Set(key, val string) error { - return c.delegate.Set(key, val) -} - -func (c *newToOldConfigerAdapter) String(key string) string { - res, _ := c.delegate.String(key) - return res -} - -func (c *newToOldConfigerAdapter) Strings(key string) []string { - res, _ := c.delegate.Strings(key) - return res -} - -func (c *newToOldConfigerAdapter) Int(key string) (int, error) { - return c.delegate.Int(key) -} - -func (c *newToOldConfigerAdapter) Int64(key string) (int64, error) { - return c.delegate.Int64(key) -} - -func (c *newToOldConfigerAdapter) Bool(key string) (bool, error) { - return c.delegate.Bool(key) -} - -func (c *newToOldConfigerAdapter) Float(key string) (float64, error) { - return c.delegate.Float(key) -} - -func (c *newToOldConfigerAdapter) DefaultString(key string, defaultVal string) string { - return c.delegate.DefaultString(key, defaultVal) -} - -func (c *newToOldConfigerAdapter) DefaultStrings(key string, defaultVal []string) []string { - return c.delegate.DefaultStrings(key, defaultVal) -} - -func (c *newToOldConfigerAdapter) DefaultInt(key string, defaultVal int) int { - return c.delegate.DefaultInt(key, defaultVal) -} - -func (c *newToOldConfigerAdapter) DefaultInt64(key string, defaultVal int64) int64 { - return c.delegate.DefaultInt64(key, defaultVal) -} - -func (c *newToOldConfigerAdapter) DefaultBool(key string, defaultVal bool) bool { - return c.delegate.DefaultBool(key, defaultVal) -} - -func (c *newToOldConfigerAdapter) DefaultFloat(key string, defaultVal float64) float64 { - return c.delegate.DefaultFloat(key, defaultVal) -} - -func (c *newToOldConfigerAdapter) DIY(key string) (interface{}, error) { - return c.delegate.DIY(key) -} - -func (c *newToOldConfigerAdapter) GetSection(section string) (map[string]string, error) { - return c.delegate.GetSection(section) -} - -func (c *newToOldConfigerAdapter) SaveConfigFile(filename string) error { - return c.delegate.SaveConfigFile(filename) -} - -type oldToNewConfigerAdapter struct { - delegate Configer -} - -func (o *oldToNewConfigerAdapter) Set(key, val string) error { - return o.delegate.Set(key, val) -} - -func (o *oldToNewConfigerAdapter) String(key string) (string, error) { - return o.delegate.String(key), nil -} - -func (o *oldToNewConfigerAdapter) Strings(key string) ([]string, error) { - return o.delegate.Strings(key), nil -} - -func (o *oldToNewConfigerAdapter) Int(key string) (int, error) { - return o.delegate.Int(key) -} - -func (o *oldToNewConfigerAdapter) Int64(key string) (int64, error) { - return o.delegate.Int64(key) -} - -func (o *oldToNewConfigerAdapter) Bool(key string) (bool, error) { - return o.delegate.Bool(key) -} - -func (o *oldToNewConfigerAdapter) Float(key string) (float64, error) { - return o.delegate.Float(key) -} - -func (o *oldToNewConfigerAdapter) DefaultString(key string, defaultVal string) string { - return o.delegate.DefaultString(key, defaultVal) -} - -func (o *oldToNewConfigerAdapter) DefaultStrings(key string, defaultVal []string) []string { - return o.delegate.DefaultStrings(key, defaultVal) -} - -func (o *oldToNewConfigerAdapter) DefaultInt(key string, defaultVal int) int { - return o.delegate.DefaultInt(key, defaultVal) -} - -func (o *oldToNewConfigerAdapter) DefaultInt64(key string, defaultVal int64) int64 { - return o.delegate.DefaultInt64(key, defaultVal) -} - -func (o *oldToNewConfigerAdapter) DefaultBool(key string, defaultVal bool) bool { - return o.delegate.DefaultBool(key, defaultVal) -} - -func (o *oldToNewConfigerAdapter) DefaultFloat(key string, defaultVal float64) float64 { - return o.delegate.DefaultFloat(key, defaultVal) -} - -func (o *oldToNewConfigerAdapter) DIY(key string) (interface{}, error) { - return o.delegate.DIY(key) -} - -func (o *oldToNewConfigerAdapter) GetSection(section string) (map[string]string, error) { - return o.delegate.GetSection(section) -} - -func (o *oldToNewConfigerAdapter) Unmarshaler(prefix string, obj interface{}, opt ...config.DecodeOption) error { - return errors.New("unsupported operation, please use actual config.Configer") -} - -func (o *oldToNewConfigerAdapter) Sub(key string) (config.Configer, error) { - return nil, errors.New("unsupported operation, please use actual config.Configer") -} - -func (o *oldToNewConfigerAdapter) OnChange(key string, fn func(value string)) { - // do nothing -} - -func (o *oldToNewConfigerAdapter) SaveConfigFile(filename string) error { - return o.delegate.SaveConfigFile(filename) -} - -type oldToNewConfigAdapter struct { - delegate Config -} - -func (o *oldToNewConfigAdapter) Parse(key string) (config.Configer, error) { - old, err := o.delegate.Parse(key) - if err != nil { - return nil, err - } - return &oldToNewConfigerAdapter{delegate: old}, nil -} - -func (o *oldToNewConfigAdapter) ParseData(data []byte) (config.Configer, error) { - old, err := o.delegate.ParseData(data) - if err != nil { - return nil, err - } - return &oldToNewConfigerAdapter{delegate: old}, nil -} diff --git a/adapter/config/config.go b/adapter/config/config.go deleted file mode 100644 index 2a96a293..00000000 --- a/adapter/config/config.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package config is used to parse config. -// Usage: -// import "github.com/beego/beego/v2/core/config" -// Examples. -// -// cnf, err := config.NewConfig("ini", "config.conf") -// -// cnf APIS: -// -// cnf.Set(key, val string) error -// cnf.String(key string) string -// cnf.Strings(key string) []string -// cnf.Int(key string) (int, error) -// cnf.Int64(key string) (int64, error) -// cnf.Bool(key string) (bool, error) -// cnf.Float(key string) (float64, error) -// cnf.DefaultString(key string, defaultVal string) string -// cnf.DefaultStrings(key string, defaultVal []string) []string -// cnf.DefaultInt(key string, defaultVal int) int -// cnf.DefaultInt64(key string, defaultVal int64) int64 -// cnf.DefaultBool(key string, defaultVal bool) bool -// cnf.DefaultFloat(key string, defaultVal float64) float64 -// cnf.DIY(key string) (interface{}, error) -// cnf.GetSection(section string) (map[string]string, error) -// cnf.SaveConfigFile(filename string) error -package config - -import ( - "github.com/beego/beego/v2/core/config" -) - -// Configer defines how to get and set value from configuration raw data. -type Configer interface { - Set(key, val string) error // support section::key type in given key when using ini type. - String(key string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. - Strings(key string) []string // get string slice - Int(key string) (int, error) - Int64(key string) (int64, error) - Bool(key string) (bool, error) - Float(key string) (float64, error) - DefaultString(key string, defaultVal string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. - DefaultStrings(key string, defaultVal []string) []string // get string slice - DefaultInt(key string, defaultVal int) int - DefaultInt64(key string, defaultVal int64) int64 - DefaultBool(key string, defaultVal bool) bool - DefaultFloat(key string, defaultVal float64) float64 - DIY(key string) (interface{}, error) - GetSection(section string) (map[string]string, error) - SaveConfigFile(filename string) error -} - -// Config is the adapter interface for parsing config file to get raw data to Configer. -type Config interface { - Parse(key string) (Configer, error) - ParseData(data []byte) (Configer, error) -} - -var adapters = make(map[string]Config) - -// Register makes a config adapter available by the adapter name. -// If Register is called twice with the same name or if driver is nil, -// it panics. -func Register(name string, adapter Config) { - config.Register(name, &oldToNewConfigAdapter{delegate: adapter}) -} - -// NewConfig adapterName is ini/json/xml/yaml. -// filename is the config file path. -func NewConfig(adapterName, filename string) (Configer, error) { - cfg, err := config.NewConfig(adapterName, filename) - if err != nil { - return nil, err - } - - // it was registered by using Register method - res, ok := cfg.(*oldToNewConfigerAdapter) - if ok { - return res.delegate, nil - } - - return &newToOldConfigerAdapter{ - delegate: cfg, - }, nil -} - -// NewConfigData adapterName is ini/json/xml/yaml. -// data is the config data. -func NewConfigData(adapterName string, data []byte) (Configer, error) { - cfg, err := config.NewConfigData(adapterName, data) - if err != nil { - return nil, err - } - - // it was registered by using Register method - res, ok := cfg.(*oldToNewConfigerAdapter) - if ok { - return res.delegate, nil - } - - return &newToOldConfigerAdapter{ - delegate: cfg, - }, nil -} - -// ExpandValueEnvForMap convert all string value with environment variable. -func ExpandValueEnvForMap(m map[string]interface{}) map[string]interface{} { - return config.ExpandValueEnvForMap(m) -} - -// ExpandValueEnv returns value of convert with environment variable. -// -// Return environment variable if value start with "${" and end with "}". -// Return default value if environment variable is empty or not exist. -// -// It accept value formats "${env}" , "${env||}}" , "${env||defaultValue}" , "defaultvalue". -// Examples: -// v1 := config.ExpandValueEnv("${GOPATH}") // return the GOPATH environment variable. -// v2 := config.ExpandValueEnv("${GOAsta||/usr/local/go}") // return the default value "/usr/local/go/". -// v3 := config.ExpandValueEnv("Astaxie") // return the value "Astaxie". -func ExpandValueEnv(value string) string { - return config.ExpandValueEnv(value) -} - -// ParseBool returns the boolean value represented by the string. -// -// It accepts 1, 1.0, t, T, TRUE, true, True, YES, yes, Yes,Y, y, ON, on, On, -// 0, 0.0, f, F, FALSE, false, False, NO, no, No, N,n, OFF, off, Off. -// Any other value returns an error. -func ParseBool(val interface{}) (value bool, err error) { - return config.ParseBool(val) -} - -// ToString converts values of any type to string. -func ToString(x interface{}) string { - return config.ToString(x) -} diff --git a/adapter/config/config_test.go b/adapter/config/config_test.go deleted file mode 100644 index 86d3a2c5..00000000 --- a/adapter/config/config_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2016 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package config - -import ( - "os" - "testing" -) - -func TestExpandValueEnv(t *testing.T) { - testCases := []struct { - item string - want string - }{ - {"", ""}, - {"$", "$"}, - {"{", "{"}, - {"{}", "{}"}, - {"${}", ""}, - {"${|}", ""}, - {"${}", ""}, - {"${{}}", ""}, - {"${{||}}", "}"}, - {"${pwd||}", ""}, - {"${pwd||}", ""}, - {"${pwd||}", ""}, - {"${pwd||}}", "}"}, - {"${pwd||{{||}}}", "{{||}}"}, - {"${GOPATH}", os.Getenv("GOPATH")}, - {"${GOPATH||}", os.Getenv("GOPATH")}, - {"${GOPATH||root}", os.Getenv("GOPATH")}, - {"${GOPATH_NOT||root}", "root"}, - {"${GOPATH_NOT||||root}", "||root"}, - } - - for _, c := range testCases { - if got := ExpandValueEnv(c.item); got != c.want { - t.Errorf("expand value error, item %q want %q, got %q", c.item, c.want, got) - } - } -} diff --git a/adapter/config/env/env.go b/adapter/config/env/env.go deleted file mode 100644 index 0be4fe6b..00000000 --- a/adapter/config/env/env.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// Copyright 2017 Faissal Elamraoui. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package env is used to parse environment. -package env - -import ( - "github.com/beego/beego/v2/core/config/env" -) - -// Get returns a value by key. -// If the key does not exist, the default value will be returned. -func Get(key string, defVal string) string { - return env.Get(key, defVal) -} - -// MustGet returns a value by key. -// If the key does not exist, it will return an error. -func MustGet(key string) (string, error) { - return env.MustGet(key) -} - -// Set sets a value in the ENV copy. -// This does not affect the child process environment. -func Set(key string, value string) { - env.Set(key, value) -} - -// MustSet sets a value in the ENV copy and the child process environment. -// It returns an error in case the set operation failed. -func MustSet(key string, value string) error { - return env.MustSet(key, value) -} - -// GetAll returns all keys/values in the current child process environment. -func GetAll() map[string]string { - return env.GetAll() -} diff --git a/adapter/config/env/env_test.go b/adapter/config/env/env_test.go deleted file mode 100644 index 3f1d4dba..00000000 --- a/adapter/config/env/env_test.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// Copyright 2017 Faissal Elamraoui. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -package env - -import ( - "os" - "testing" -) - -func TestEnvGet(t *testing.T) { - gopath := Get("GOPATH", "") - if gopath != os.Getenv("GOPATH") { - t.Error("expected GOPATH not empty.") - } - - noExistVar := Get("NOEXISTVAR", "foo") - if noExistVar != "foo" { - t.Errorf("expected NOEXISTVAR to equal foo, got %s.", noExistVar) - } -} - -func TestEnvMustGet(t *testing.T) { - gopath, err := MustGet("GOPATH") - if err != nil { - t.Error(err) - } - - if gopath != os.Getenv("GOPATH") { - t.Errorf("expected GOPATH to be the same, got %s.", gopath) - } - - _, err = MustGet("NOEXISTVAR") - if err == nil { - t.Error("expected error to be non-nil") - } -} - -func TestEnvSet(t *testing.T) { - Set("MYVAR", "foo") - myVar := Get("MYVAR", "bar") - if myVar != "foo" { - t.Errorf("expected MYVAR to equal foo, got %s.", myVar) - } -} - -func TestEnvMustSet(t *testing.T) { - err := MustSet("FOO", "bar") - if err != nil { - t.Error(err) - } - - fooVar := os.Getenv("FOO") - if fooVar != "bar" { - t.Errorf("expected FOO variable to equal bar, got %s.", fooVar) - } -} - -func TestEnvGetAll(t *testing.T) { - envMap := GetAll() - if len(envMap) == 0 { - t.Error("expected environment not empty.") - } -} diff --git a/adapter/config/fake.go b/adapter/config/fake.go deleted file mode 100644 index b87ead34..00000000 --- a/adapter/config/fake.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package config - -import ( - "github.com/beego/beego/v2/core/config" -) - -// NewFakeConfig return a fake Configer -func NewFakeConfig() Configer { - config := config.NewFakeConfig() - return &newToOldConfigerAdapter{delegate: config} -} diff --git a/adapter/config/ini_test.go b/adapter/config/ini_test.go deleted file mode 100644 index 997d3f68..00000000 --- a/adapter/config/ini_test.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package config - -import ( - "fmt" - "io/ioutil" - "os" - "strings" - "testing" -) - -func TestIni(t *testing.T) { - var ( - inicontext = ` -;comment one -#comment two -appname = beeapi -httpport = 8080 -mysqlport = 3600 -PI = 3.1415976 -runmode = "dev" -autorender = false -copyrequestbody = true -session= on -cookieon= off -newreg = OFF -needlogin = ON -enableSession = Y -enableCookie = N -flag = 1 -path1 = ${GOPATH} -path2 = ${GOPATH||/home/go} -[demo] -key1="asta" -key2 = "xie" -CaseInsensitive = true -peers = one;two;three -password = ${GOPATH} -` - - keyValue = map[string]interface{}{ - "appname": "beeapi", - "httpport": 8080, - "mysqlport": int64(3600), - "pi": 3.1415976, - "runmode": "dev", - "autorender": false, - "copyrequestbody": true, - "session": true, - "cookieon": false, - "newreg": false, - "needlogin": true, - "enableSession": true, - "enableCookie": false, - "flag": true, - "path1": os.Getenv("GOPATH"), - "path2": os.Getenv("GOPATH"), - "demo::key1": "asta", - "demo::key2": "xie", - "demo::CaseInsensitive": true, - "demo::peers": []string{"one", "two", "three"}, - "demo::password": os.Getenv("GOPATH"), - "null": "", - "demo2::key1": "", - "error": "", - "emptystrings": []string{}, - } - ) - - cfgFile := "testini.conf" - f, err := os.Create(cfgFile) - if err != nil { - t.Fatal(err) - } - _, err = f.WriteString(inicontext) - if err != nil { - f.Close() - t.Fatal(err) - } - f.Close() - defer os.Remove(cfgFile) - iniconf, err := NewConfig("ini", cfgFile) - if err != nil { - t.Fatal(err) - } - for k, v := range keyValue { - var err error - var value interface{} - switch v.(type) { - case int: - value, err = iniconf.Int(k) - case int64: - value, err = iniconf.Int64(k) - case float64: - value, err = iniconf.Float(k) - case bool: - value, err = iniconf.Bool(k) - case []string: - value = iniconf.Strings(k) - case string: - value = iniconf.String(k) - default: - value, err = iniconf.DIY(k) - } - if err != nil { - t.Fatalf("get key %q value fail,err %s", k, err) - } else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) { - t.Fatalf("get key %q value, want %v got %v .", k, v, value) - } - - } - if err = iniconf.Set("name", "astaxie"); err != nil { - t.Fatal(err) - } - if iniconf.String("name") != "astaxie" { - t.Fatal("get name error") - } -} - -func TestIniSave(t *testing.T) { - const ( - inicontext = ` -app = app -;comment one -#comment two -# comment three -appname = beeapi -httpport = 8080 -# DB Info -# enable db -[dbinfo] -# db type name -# support mysql,sqlserver -name = mysql -` - - saveResult = ` -app=app -#comment one -#comment two -# comment three -appname=beeapi -httpport=8080 - -# DB Info -# enable db -[dbinfo] -# db type name -# support mysql,sqlserver -name=mysql -` - ) - cfg, err := NewConfigData("ini", []byte(inicontext)) - if err != nil { - t.Fatal(err) - } - name := "newIniConfig.ini" - if err := cfg.SaveConfigFile(name); err != nil { - t.Fatal(err) - } - defer os.Remove(name) - - if data, err := ioutil.ReadFile(name); err != nil { - t.Fatal(err) - } else { - cfgData := string(data) - datas := strings.Split(saveResult, "\n") - for _, line := range datas { - if !strings.Contains(cfgData, line+"\n") { - t.Fatalf("different after save ini config file. need contains %q", line) - } - } - - } -} diff --git a/adapter/config/json_test.go b/adapter/config/json_test.go deleted file mode 100644 index 2f2c27c3..00000000 --- a/adapter/config/json_test.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package config - -import ( - "fmt" - "os" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestJsonStartsWithArray(t *testing.T) { - const jsoncontextwitharray = `[ - { - "url": "user", - "serviceAPI": "http://www.test.com/user" - }, - { - "url": "employee", - "serviceAPI": "http://www.test.com/employee" - } -]` - cfgFileName := "testjsonWithArray.conf" - f, err := os.Create(cfgFileName) - if err != nil { - t.Fatal(err) - } - _, err = f.WriteString(jsoncontextwitharray) - if err != nil { - f.Close() - t.Fatal(err) - } - f.Close() - defer os.Remove(cfgFileName) - jsonconf, err := NewConfig("json", cfgFileName) - if err != nil { - t.Fatal(err) - } - rootArray, err := jsonconf.DIY("rootArray") - if err != nil { - t.Error("array does not exist as element") - } - rootArrayCasted := rootArray.([]interface{}) - if rootArrayCasted == nil { - t.Error("array from root is nil") - } else { - elem := rootArrayCasted[0].(map[string]interface{}) - if elem["url"] != "user" || elem["serviceAPI"] != "http://www.test.com/user" { - t.Error("array[0] values are not valid") - } - - elem2 := rootArrayCasted[1].(map[string]interface{}) - if elem2["url"] != "employee" || elem2["serviceAPI"] != "http://www.test.com/employee" { - t.Error("array[1] values are not valid") - } - } -} - -func TestJson(t *testing.T) { - var ( - jsoncontext = `{ -"appname": "beeapi", -"testnames": "foo;bar", -"httpport": 8080, -"mysqlport": 3600, -"PI": 3.1415976, -"runmode": "dev", -"autorender": false, -"copyrequestbody": true, -"session": "on", -"cookieon": "off", -"newreg": "OFF", -"needlogin": "ON", -"enableSession": "Y", -"enableCookie": "N", -"flag": 1, -"path1": "${GOPATH}", -"path2": "${GOPATH||/home/go}", -"database": { - "host": "host", - "port": "port", - "database": "database", - "username": "username", - "password": "${GOPATH}", - "conns":{ - "maxconnection":12, - "autoconnect":true, - "connectioninfo":"info", - "root": "${GOPATH}" - } - } -}` - keyValue = map[string]interface{}{ - "appname": "beeapi", - "testnames": []string{"foo", "bar"}, - "httpport": 8080, - "mysqlport": int64(3600), - "PI": 3.1415976, - "runmode": "dev", - "autorender": false, - "copyrequestbody": true, - "session": true, - "cookieon": false, - "newreg": false, - "needlogin": true, - "enableSession": true, - "enableCookie": false, - "flag": true, - "path1": os.Getenv("GOPATH"), - "path2": os.Getenv("GOPATH"), - "database::host": "host", - "database::port": "port", - "database::database": "database", - "database::password": os.Getenv("GOPATH"), - "database::conns::maxconnection": 12, - "database::conns::autoconnect": true, - "database::conns::connectioninfo": "info", - "database::conns::root": os.Getenv("GOPATH"), - "unknown": "", - } - ) - - cfgFileName := "testjson.conf" - f, err := os.Create(cfgFileName) - if err != nil { - t.Fatal(err) - } - _, err = f.WriteString(jsoncontext) - if err != nil { - f.Close() - t.Fatal(err) - } - f.Close() - defer os.Remove(cfgFileName) - jsonconf, err := NewConfig("json", cfgFileName) - if err != nil { - t.Fatal(err) - } - - for k, v := range keyValue { - var err error - var value interface{} - switch v.(type) { - case int: - value, err = jsonconf.Int(k) - case int64: - value, err = jsonconf.Int64(k) - case float64: - value, err = jsonconf.Float(k) - case bool: - value, err = jsonconf.Bool(k) - case []string: - value = jsonconf.Strings(k) - case string: - value = jsonconf.String(k) - default: - value, err = jsonconf.DIY(k) - } - - assert.Nil(t, err) - assert.Equal(t, fmt.Sprintf("%v", v), fmt.Sprintf("%v", value)) - } - - assert.Nil(t, jsonconf.Set("name", "astaxie")) - - assert.Equal(t, "astaxie", jsonconf.String("name")) - - db, err := jsonconf.DIY("database") - assert.Nil(t, err) - - m, ok := db.(map[string]interface{}) - assert.True(t, ok) - assert.Equal(t, "host", m["host"]) - - _, err = jsonconf.Int("unknown") - assert.NotNil(t, err) - - _, err = jsonconf.Int64("unknown") - assert.NotNil(t, err) - - _, err = jsonconf.Float("unknown") - assert.NotNil(t, err) - - _, err = jsonconf.DIY("unknown") - assert.NotNil(t, err) - - val := jsonconf.String("unknown") - assert.Equal(t, "", val) - - _, err = jsonconf.Bool("unknown") - assert.NotNil(t, err) - - assert.True(t, jsonconf.DefaultBool("unknown", true)) -} diff --git a/adapter/config/xml/xml.go b/adapter/config/xml/xml.go deleted file mode 100644 index d5ba6fd0..00000000 --- a/adapter/config/xml/xml.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package xml for config provider. -// -// depend on github.com/beego/x2j. -// -// go install github.com/beego/x2j. -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/core/config/xml" -// "github.com/beego/beego/v2/core/config" -// ) -// -// cnf, err := config.NewConfig("xml", "config.xml") -// -package xml - -import ( - _ "github.com/beego/beego/v2/core/config/xml" -) diff --git a/adapter/config/xml/xml_test.go b/adapter/config/xml/xml_test.go deleted file mode 100644 index 48424ef9..00000000 --- a/adapter/config/xml/xml_test.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package xml - -import ( - "fmt" - "os" - "testing" - - "github.com/beego/beego/v2/adapter/config" -) - -func TestXML(t *testing.T) { - var ( - // xml parse should incluce in tags - xmlcontext = ` - -beeapi -8080 -3600 -3.1415976 -dev -false -true -${GOPATH} -${GOPATH||/home/go} - -1 -MySection - - -` - keyValue = map[string]interface{}{ - "appname": "beeapi", - "httpport": 8080, - "mysqlport": int64(3600), - "PI": 3.1415976, - "runmode": "dev", - "autorender": false, - "copyrequestbody": true, - "path1": os.Getenv("GOPATH"), - "path2": os.Getenv("GOPATH"), - "error": "", - "emptystrings": []string{}, - } - ) - - cfgFileName := "testxml.conf" - f, err := os.Create(cfgFileName) - if err != nil { - t.Fatal(err) - } - _, err = f.WriteString(xmlcontext) - if err != nil { - f.Close() - t.Fatal(err) - } - f.Close() - defer os.Remove(cfgFileName) - - xmlconf, err := config.NewConfig("xml", cfgFileName) - if err != nil { - t.Fatal(err) - } - - var xmlsection map[string]string - xmlsection, err = xmlconf.GetSection("mysection") - if err != nil { - t.Fatal(err) - } - - if len(xmlsection) == 0 { - t.Error("section should not be empty") - } - - for k, v := range keyValue { - - var ( - value interface{} - err error - ) - - switch v.(type) { - case int: - value, err = xmlconf.Int(k) - case int64: - value, err = xmlconf.Int64(k) - case float64: - value, err = xmlconf.Float(k) - case bool: - value, err = xmlconf.Bool(k) - case []string: - value = xmlconf.Strings(k) - case string: - value = xmlconf.String(k) - default: - value, err = xmlconf.DIY(k) - } - if err != nil { - t.Errorf("get key %q value fatal,%v err %s", k, v, err) - } else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) { - t.Errorf("get key %q value, want %v got %v .", k, v, value) - } - - } - - if err = xmlconf.Set("name", "astaxie"); err != nil { - t.Fatal(err) - } - if xmlconf.String("name") != "astaxie" { - t.Fatal("get name error") - } -} diff --git a/adapter/config/yaml/yaml.go b/adapter/config/yaml/yaml.go deleted file mode 100644 index ef6296fa..00000000 --- a/adapter/config/yaml/yaml.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package yaml for config provider -// -// depend on github.com/beego/goyaml2 -// -// go install github.com/beego/goyaml2 -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/core/config/yaml" -// "github.com/beego/beego/v2/core/config" -// ) -// -// cnf, err := config.NewConfig("yaml", "config.yaml") -// -package yaml - -import ( - _ "github.com/beego/beego/v2/core/config/yaml" -) diff --git a/adapter/config/yaml/yaml_test.go b/adapter/config/yaml/yaml_test.go deleted file mode 100644 index ac0245dd..00000000 --- a/adapter/config/yaml/yaml_test.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "fmt" - "os" - "testing" - - "github.com/beego/beego/v2/adapter/config" -) - -func TestYaml(t *testing.T) { - var ( - yamlcontext = ` -"appname": beeapi -"httpport": 8080 -"mysqlport": 3600 -"PI": 3.1415976 -"runmode": dev -"autorender": false -"copyrequestbody": true -"PATH": GOPATH -"path1": ${GOPATH} -"path2": ${GOPATH||/home/go} -"empty": "" -` - - keyValue = map[string]interface{}{ - "appname": "beeapi", - "httpport": 8080, - "mysqlport": int64(3600), - "PI": 3.1415976, - "runmode": "dev", - "autorender": false, - "copyrequestbody": true, - "PATH": "GOPATH", - "path1": os.Getenv("GOPATH"), - "path2": os.Getenv("GOPATH"), - "error": "", - "emptystrings": []string{}, - } - ) - cfgFileName := "testyaml.conf" - f, err := os.Create(cfgFileName) - if err != nil { - t.Fatal(err) - } - _, err = f.WriteString(yamlcontext) - if err != nil { - f.Close() - t.Fatal(err) - } - f.Close() - defer os.Remove(cfgFileName) - yamlconf, err := config.NewConfig("yaml", cfgFileName) - if err != nil { - t.Fatal(err) - } - - if yamlconf.String("appname") != "beeapi" { - t.Fatal("appname not equal to beeapi") - } - - for k, v := range keyValue { - - var ( - value interface{} - err error - ) - - switch v.(type) { - case int: - value, err = yamlconf.Int(k) - case int64: - value, err = yamlconf.Int64(k) - case float64: - value, err = yamlconf.Float(k) - case bool: - value, err = yamlconf.Bool(k) - case []string: - value = yamlconf.Strings(k) - case string: - value = yamlconf.String(k) - default: - value, err = yamlconf.DIY(k) - } - if err != nil { - t.Errorf("get key %q value fatal,%v err %s", k, v, err) - } else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) { - t.Errorf("get key %q value, want %v got %v .", k, v, value) - } - - } - - if err = yamlconf.Set("name", "astaxie"); err != nil { - t.Fatal(err) - } - if yamlconf.String("name") != "astaxie" { - t.Fatal("get name error") - } -} diff --git a/adapter/context/acceptencoder.go b/adapter/context/acceptencoder.go deleted file mode 100644 index 69a3acbc..00000000 --- a/adapter/context/acceptencoder.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2015 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package context - -import ( - "io" - "net/http" - "os" - - "github.com/beego/beego/v2/server/web/context" -) - -// InitGzip init the gzipcompress -func InitGzip(minLength, compressLevel int, methods []string) { - context.InitGzip(minLength, compressLevel, methods) -} - -// WriteFile reads from file and writes to writer by the specific encoding(gzip/deflate) -func WriteFile(encoding string, writer io.Writer, file *os.File) (bool, string, error) { - return context.WriteFile(encoding, writer, file) -} - -// WriteBody reads writes content to writer by the specific encoding(gzip/deflate) -func WriteBody(encoding string, writer io.Writer, content []byte) (bool, string, error) { - return context.WriteBody(encoding, writer, content) -} - -// ParseEncoding will extract the right encoding for response -// the Accept-Encoding's sec is here: -// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3 -func ParseEncoding(r *http.Request) string { - return context.ParseEncoding(r) -} diff --git a/adapter/context/context.go b/adapter/context/context.go deleted file mode 100644 index 82f8e63a..00000000 --- a/adapter/context/context.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package context provide the context utils -// Usage: -// -// import "github.com/beego/beego/v2/server/web/context" -// -// ctx := context.Context{Request:req,ResponseWriter:rw} -// -package context - -import ( - "bufio" - "net" - "net/http" - - "github.com/beego/beego/v2/server/web/context" -) - -// commonly used mime-types -const ( - ApplicationJSON = context.ApplicationJSON - ApplicationXML = context.ApplicationXML - ApplicationYAML = context.ApplicationYAML - TextXML = context.TextXML -) - -// NewContext return the Context with Input and Output -func NewContext() *Context { - return (*Context)(context.NewContext()) -} - -// Context Http request context struct including BeegoInput, BeegoOutput, http.Request and http.ResponseWriter. -// BeegoInput and BeegoOutput provides some api to operate request and response more easily. -type Context context.Context - -// Reset init Context, BeegoInput and BeegoOutput -func (ctx *Context) Reset(rw http.ResponseWriter, r *http.Request) { - (*context.Context)(ctx).Reset(rw, r) -} - -// Redirect does redirection to localurl with http header status code. -func (ctx *Context) Redirect(status int, localurl string) { - (*context.Context)(ctx).Redirect(status, localurl) -} - -// Abort stops this request. -// if beego.ErrorMaps exists, panic body. -func (ctx *Context) Abort(status int, body string) { - (*context.Context)(ctx).Abort(status, body) -} - -// WriteString Write string to response body. -// it sends response body. -func (ctx *Context) WriteString(content string) { - (*context.Context)(ctx).WriteString(content) -} - -// GetCookie Get cookie from request by a given key. -// It's alias of BeegoInput.Cookie. -func (ctx *Context) GetCookie(key string) string { - return (*context.Context)(ctx).GetCookie(key) -} - -// SetCookie Set cookie for response. -// It's alias of BeegoOutput.Cookie. -func (ctx *Context) SetCookie(name string, value string, others ...interface{}) { - (*context.Context)(ctx).SetCookie(name, value, others...) -} - -// GetSecureCookie Get secure cookie from request by a given key. -func (ctx *Context) GetSecureCookie(Secret, key string) (string, bool) { - return (*context.Context)(ctx).GetSecureCookie(Secret, key) -} - -// SetSecureCookie Set Secure cookie for response. -func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interface{}) { - (*context.Context)(ctx).SetSecureCookie(Secret, name, value, others...) -} - -// XSRFToken creates a xsrf token string and returns. -func (ctx *Context) XSRFToken(key string, expire int64) string { - return (*context.Context)(ctx).XSRFToken(key, expire) -} - -// CheckXSRFCookie checks xsrf token in this request is valid or not. -// the token can provided in request header "X-Xsrftoken" and "X-CsrfToken" -// or in form field value named as "_xsrf". -func (ctx *Context) CheckXSRFCookie() bool { - return (*context.Context)(ctx).CheckXSRFCookie() -} - -// RenderMethodResult renders the return value of a controller method to the output -func (ctx *Context) RenderMethodResult(result interface{}) { - (*context.Context)(ctx).RenderMethodResult(result) -} - -// Response is a wrapper for the http.ResponseWriter -// started set to true if response was written to then don't execute other handler -type Response context.Response - -// Write writes the data to the connection as part of an HTTP reply, -// and sets `started` to true. -// started means the response has sent out. -func (r *Response) Write(p []byte) (int, error) { - return (*context.Response)(r).Write(p) -} - -// WriteHeader sends an HTTP response header with status code, -// and sets `started` to true. -func (r *Response) WriteHeader(code int) { - (*context.Response)(r).WriteHeader(code) -} - -// Hijack hijacker for http -func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) { - return (*context.Response)(r).Hijack() -} - -// Flush http.Flusher -func (r *Response) Flush() { - (*context.Response)(r).Flush() -} - -// CloseNotify http.CloseNotifier -func (r *Response) CloseNotify() <-chan bool { - return (*context.Response)(r).CloseNotify() -} - -// Pusher http.Pusher -func (r *Response) Pusher() (pusher http.Pusher) { - return (*context.Response)(r).Pusher() -} diff --git a/adapter/context/input.go b/adapter/context/input.go deleted file mode 100644 index def81bf8..00000000 --- a/adapter/context/input.go +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package context - -import ( - "github.com/beego/beego/v2/server/web/context" -) - -// BeegoInput operates the http request header, data, cookie and body. -// it also contains router params and current session. -type BeegoInput context.BeegoInput - -// NewInput return BeegoInput generated by Context. -func NewInput() *BeegoInput { - return (*BeegoInput)(context.NewInput()) -} - -// Reset init the BeegoInput -func (input *BeegoInput) Reset(ctx *Context) { - (*context.BeegoInput)(input).Reset((*context.Context)(ctx)) -} - -// Protocol returns request protocol name, such as HTTP/1.1 . -func (input *BeegoInput) Protocol() string { - return (*context.BeegoInput)(input).Protocol() -} - -// URI returns full request url with query string, fragment. -func (input *BeegoInput) URI() string { - return input.Context.Request.RequestURI -} - -// URL returns request url path (without query string, fragment). -func (input *BeegoInput) URL() string { - return (*context.BeegoInput)(input).URL() -} - -// Site returns base site url as scheme://domain type. -func (input *BeegoInput) Site() string { - return (*context.BeegoInput)(input).Site() -} - -// Scheme returns request scheme as "http" or "https". -func (input *BeegoInput) Scheme() string { - return (*context.BeegoInput)(input).Scheme() -} - -// Domain returns host name. -// Alias of Host method. -func (input *BeegoInput) Domain() string { - return (*context.BeegoInput)(input).Domain() -} - -// Host returns host name. -// if no host info in request, return localhost. -func (input *BeegoInput) Host() string { - return (*context.BeegoInput)(input).Host() -} - -// Method returns http request method. -func (input *BeegoInput) Method() string { - return (*context.BeegoInput)(input).Method() -} - -// Is returns boolean of this request is on given method, such as Is("POST"). -func (input *BeegoInput) Is(method string) bool { - return (*context.BeegoInput)(input).Is(method) -} - -// IsGet Is this a GET method request? -func (input *BeegoInput) IsGet() bool { - return (*context.BeegoInput)(input).IsGet() -} - -// IsPost Is this a POST method request? -func (input *BeegoInput) IsPost() bool { - return (*context.BeegoInput)(input).IsPost() -} - -// IsHead Is this a Head method request? -func (input *BeegoInput) IsHead() bool { - return (*context.BeegoInput)(input).IsHead() -} - -// IsOptions Is this an OPTIONS method request? -func (input *BeegoInput) IsOptions() bool { - return (*context.BeegoInput)(input).IsOptions() -} - -// IsPut Is this a PUT method request? -func (input *BeegoInput) IsPut() bool { - return (*context.BeegoInput)(input).IsPut() -} - -// IsDelete Is this a DELETE method request? -func (input *BeegoInput) IsDelete() bool { - return (*context.BeegoInput)(input).IsDelete() -} - -// IsPatch Is this a PATCH method request? -func (input *BeegoInput) IsPatch() bool { - return (*context.BeegoInput)(input).IsPatch() -} - -// IsAjax returns boolean of this request is generated by ajax. -func (input *BeegoInput) IsAjax() bool { - return (*context.BeegoInput)(input).IsAjax() -} - -// IsSecure returns boolean of this request is in https. -func (input *BeegoInput) IsSecure() bool { - return (*context.BeegoInput)(input).IsSecure() -} - -// IsWebsocket returns boolean of this request is in webSocket. -func (input *BeegoInput) IsWebsocket() bool { - return (*context.BeegoInput)(input).IsWebsocket() -} - -// IsUpload returns boolean of whether file uploads in this request or not.. -func (input *BeegoInput) IsUpload() bool { - return (*context.BeegoInput)(input).IsUpload() -} - -// AcceptsHTML Checks if request accepts html response -func (input *BeegoInput) AcceptsHTML() bool { - return (*context.BeegoInput)(input).AcceptsHTML() -} - -// AcceptsXML Checks if request accepts xml response -func (input *BeegoInput) AcceptsXML() bool { - return (*context.BeegoInput)(input).AcceptsXML() -} - -// AcceptsJSON Checks if request accepts json response -func (input *BeegoInput) AcceptsJSON() bool { - return (*context.BeegoInput)(input).AcceptsJSON() -} - -// AcceptsYAML Checks if request accepts json response -func (input *BeegoInput) AcceptsYAML() bool { - return (*context.BeegoInput)(input).AcceptsYAML() -} - -// IP returns request client ip. -// if in proxy, return first proxy id. -// if error, return RemoteAddr. -func (input *BeegoInput) IP() string { - return (*context.BeegoInput)(input).IP() -} - -// Proxy returns proxy client ips slice. -func (input *BeegoInput) Proxy() []string { - return (*context.BeegoInput)(input).Proxy() -} - -// Referer returns http referer header. -func (input *BeegoInput) Referer() string { - return (*context.BeegoInput)(input).Referer() -} - -// Refer returns http referer header. -func (input *BeegoInput) Refer() string { - return (*context.BeegoInput)(input).Refer() -} - -// SubDomains returns sub domain string. -// if aa.bb.domain.com, returns aa.bb . -func (input *BeegoInput) SubDomains() string { - return (*context.BeegoInput)(input).SubDomains() -} - -// Port returns request client port. -// when error or empty, return 80. -func (input *BeegoInput) Port() int { - return (*context.BeegoInput)(input).Port() -} - -// UserAgent returns request client user agent string. -func (input *BeegoInput) UserAgent() string { - return (*context.BeegoInput)(input).UserAgent() -} - -// ParamsLen return the length of the params -func (input *BeegoInput) ParamsLen() int { - return (*context.BeegoInput)(input).ParamsLen() -} - -// Param returns router param by a given key. -func (input *BeegoInput) Param(key string) string { - return (*context.BeegoInput)(input).Param(key) -} - -// Params returns the map[key]value. -func (input *BeegoInput) Params() map[string]string { - return (*context.BeegoInput)(input).Params() -} - -// SetParam will set the param with key and value -func (input *BeegoInput) SetParam(key, val string) { - (*context.BeegoInput)(input).SetParam(key, val) -} - -// ResetParams clears any of the input's Params -// This function is used to clear parameters so they may be reset between filter -// passes. -func (input *BeegoInput) ResetParams() { - (*context.BeegoInput)(input).ResetParams() -} - -// Query returns input data item string by a given string. -func (input *BeegoInput) Query(key string) string { - return (*context.BeegoInput)(input).Query(key) -} - -// Header returns request header item string by a given string. -// if non-existed, return empty string. -func (input *BeegoInput) Header(key string) string { - return (*context.BeegoInput)(input).Header(key) -} - -// Cookie returns request cookie item string by a given key. -// if non-existed, return empty string. -func (input *BeegoInput) Cookie(key string) string { - return (*context.BeegoInput)(input).Cookie(key) -} - -// Session returns current session item value by a given key. -// if non-existed, return nil. -func (input *BeegoInput) Session(key interface{}) interface{} { - return (*context.BeegoInput)(input).Session(key) -} - -// CopyBody returns the raw request body data as bytes. -func (input *BeegoInput) CopyBody(MaxMemory int64) []byte { - return (*context.BeegoInput)(input).CopyBody(MaxMemory) -} - -// Data return the implicit data in the input -func (input *BeegoInput) Data() map[interface{}]interface{} { - return (*context.BeegoInput)(input).Data() -} - -// GetData returns the stored data in this context. -func (input *BeegoInput) GetData(key interface{}) interface{} { - return (*context.BeegoInput)(input).GetData(key) -} - -// SetData stores data with given key in this context. -// This data are only available in this context. -func (input *BeegoInput) SetData(key, val interface{}) { - (*context.BeegoInput)(input).SetData(key, val) -} - -// ParseFormOrMulitForm parseForm or parseMultiForm based on Content-type -func (input *BeegoInput) ParseFormOrMulitForm(maxMemory int64) error { - return (*context.BeegoInput)(input).ParseFormOrMultiForm(maxMemory) -} - -// Bind data from request.Form[key] to dest -// like /?id=123&isok=true&ft=1.2&ol[0]=1&ol[1]=2&ul[]=str&ul[]=array&user.Name=astaxie -// var id int beegoInput.Bind(&id, "id") id ==123 -// var isok bool beegoInput.Bind(&isok, "isok") isok ==true -// var ft float64 beegoInput.Bind(&ft, "ft") ft ==1.2 -// ol := make([]int, 0, 2) beegoInput.Bind(&ol, "ol") ol ==[1 2] -// ul := make([]string, 0, 2) beegoInput.Bind(&ul, "ul") ul ==[str array] -// user struct{Name} beegoInput.Bind(&user, "user") user == {Name:"astaxie"} -func (input *BeegoInput) Bind(dest interface{}, key string) error { - return (*context.BeegoInput)(input).Bind(dest, key) -} diff --git a/adapter/context/output.go b/adapter/context/output.go deleted file mode 100644 index 46edd343..00000000 --- a/adapter/context/output.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package context - -import ( - "github.com/beego/beego/v2/server/web/context" -) - -// BeegoOutput does work for sending response header. -type BeegoOutput context.BeegoOutput - -// NewOutput returns new BeegoOutput. -// it contains nothing now. -func NewOutput() *BeegoOutput { - return (*BeegoOutput)(context.NewOutput()) -} - -// Reset init BeegoOutput -func (output *BeegoOutput) Reset(ctx *Context) { - (*context.BeegoOutput)(output).Reset((*context.Context)(ctx)) -} - -// Header sets response header item string via given key. -func (output *BeegoOutput) Header(key, val string) { - (*context.BeegoOutput)(output).Header(key, val) -} - -// Body sets response body content. -// if EnableGzip, compress content string. -// it sends out response body directly. -func (output *BeegoOutput) Body(content []byte) error { - return (*context.BeegoOutput)(output).Body(content) -} - -// Cookie sets cookie value via given key. -// others are ordered as cookie's max age time, path,domain, secure and httponly. -func (output *BeegoOutput) Cookie(name string, value string, others ...interface{}) { - (*context.BeegoOutput)(output).Cookie(name, value, others...) -} - -// JSON writes json to response body. -// if encoding is true, it converts utf-8 to \u0000 type. -func (output *BeegoOutput) JSON(data interface{}, hasIndent bool, encoding bool) error { - return (*context.BeegoOutput)(output).JSON(data, hasIndent, encoding) -} - -// YAML writes yaml to response body. -func (output *BeegoOutput) YAML(data interface{}) error { - return (*context.BeegoOutput)(output).YAML(data) -} - -// JSONP writes jsonp to response body. -func (output *BeegoOutput) JSONP(data interface{}, hasIndent bool) error { - return (*context.BeegoOutput)(output).JSONP(data, hasIndent) -} - -// XML writes xml string to response body. -func (output *BeegoOutput) XML(data interface{}, hasIndent bool) error { - return (*context.BeegoOutput)(output).XML(data, hasIndent) -} - -// ServeFormatted serve YAML, XML OR JSON, depending on the value of the Accept header -func (output *BeegoOutput) ServeFormatted(data interface{}, hasIndent bool, hasEncode ...bool) { - (*context.BeegoOutput)(output).ServeFormatted(data, hasIndent, hasEncode...) -} - -// Download forces response for download file. -// it prepares the download response header automatically. -func (output *BeegoOutput) Download(file string, filename ...string) { - (*context.BeegoOutput)(output).Download(file, filename...) -} - -// ContentType sets the content type from ext string. -// MIME type is given in mime package. -func (output *BeegoOutput) ContentType(ext string) { - (*context.BeegoOutput)(output).ContentType(ext) -} - -// SetStatus sets response status code. -// It writes response header directly. -func (output *BeegoOutput) SetStatus(status int) { - (*context.BeegoOutput)(output).SetStatus(status) -} - -// IsCachable returns boolean of this request is cached. -// HTTP 304 means cached. -func (output *BeegoOutput) IsCachable() bool { - return (*context.BeegoOutput)(output).IsCachable() -} - -// IsEmpty returns boolean of this request is empty. -// HTTP 201,204 and 304 means empty. -func (output *BeegoOutput) IsEmpty() bool { - return (*context.BeegoOutput)(output).IsEmpty() -} - -// IsOk returns boolean of this request runs well. -// HTTP 200 means ok. -func (output *BeegoOutput) IsOk() bool { - return (*context.BeegoOutput)(output).IsOk() -} - -// IsSuccessful returns boolean of this request runs successfully. -// HTTP 2xx means ok. -func (output *BeegoOutput) IsSuccessful() bool { - return (*context.BeegoOutput)(output).IsSuccessful() -} - -// IsRedirect returns boolean of this request is redirection header. -// HTTP 301,302,307 means redirection. -func (output *BeegoOutput) IsRedirect() bool { - return (*context.BeegoOutput)(output).IsRedirect() -} - -// IsForbidden returns boolean of this request is forbidden. -// HTTP 403 means forbidden. -func (output *BeegoOutput) IsForbidden() bool { - return (*context.BeegoOutput)(output).IsForbidden() -} - -// IsNotFound returns boolean of this request is not found. -// HTTP 404 means not found. -func (output *BeegoOutput) IsNotFound() bool { - return (*context.BeegoOutput)(output).IsNotFound() -} - -// IsClientError returns boolean of this request client sends error data. -// HTTP 4xx means client error. -func (output *BeegoOutput) IsClientError() bool { - return (*context.BeegoOutput)(output).IsClientError() -} - -// IsServerError returns boolean of this server handler errors. -// HTTP 5xx means server internal error. -func (output *BeegoOutput) IsServerError() bool { - return (*context.BeegoOutput)(output).IsServerError() -} - -// Session sets session item value with given key. -func (output *BeegoOutput) Session(name interface{}, value interface{}) { - (*context.BeegoOutput)(output).Session(name, value) -} diff --git a/adapter/context/param/conv.go b/adapter/context/param/conv.go deleted file mode 100644 index ec4c6b7e..00000000 --- a/adapter/context/param/conv.go +++ /dev/null @@ -1,18 +0,0 @@ -package param - -import ( - "reflect" - - beecontext "github.com/beego/beego/v2/adapter/context" - "github.com/beego/beego/v2/server/web/context" - "github.com/beego/beego/v2/server/web/context/param" -) - -// ConvertParams converts http method params to values that will be passed to the method controller as arguments -func ConvertParams(methodParams []*MethodParam, methodType reflect.Type, ctx *beecontext.Context) (result []reflect.Value) { - nps := make([]*param.MethodParam, 0, len(methodParams)) - for _, mp := range methodParams { - nps = append(nps, (*param.MethodParam)(mp)) - } - return param.ConvertParams(nps, methodType, (*context.Context)(ctx)) -} diff --git a/adapter/context/param/conv_test.go b/adapter/context/param/conv_test.go deleted file mode 100644 index b31a8afc..00000000 --- a/adapter/context/param/conv_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 beego -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package param - -import ( - "reflect" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/beego/beego/v2/adapter/context" -) - -// Demo is used to test, it's empty -func Demo(i int) { -} - -func TestConvertParams(t *testing.T) { - res := ConvertParams(nil, reflect.TypeOf(Demo), context.NewContext()) - assert.Equal(t, 0, len(res)) - ctx := context.NewContext() - ctx.Input.RequestBody = []byte("11") - res = ConvertParams([]*MethodParam{ - New("A", InBody), - }, reflect.TypeOf(Demo), ctx) - assert.Equal(t, int64(11), res[0].Int()) -} diff --git a/adapter/context/param/methodparams.go b/adapter/context/param/methodparams.go deleted file mode 100644 index 000539db..00000000 --- a/adapter/context/param/methodparams.go +++ /dev/null @@ -1,29 +0,0 @@ -package param - -import ( - "github.com/beego/beego/v2/server/web/context/param" -) - -// MethodParam keeps param information to be auto passed to controller methods -type MethodParam param.MethodParam - -// New creates a new MethodParam with name and specific options -func New(name string, opts ...MethodParamOption) *MethodParam { - newOps := make([]param.MethodParamOption, 0, len(opts)) - for _, o := range opts { - newOps = append(newOps, oldMpoToNew(o)) - } - return (*MethodParam)(param.New(name, newOps...)) -} - -// Make creates an array of MethodParmas or an empty array -func Make(list ...*MethodParam) []*MethodParam { - if len(list) > 0 { - return list - } - return nil -} - -func (mp *MethodParam) String() string { - return (*param.MethodParam)(mp).String() -} diff --git a/adapter/context/param/methodparams_test.go b/adapter/context/param/methodparams_test.go deleted file mode 100644 index 9d5155bf..00000000 --- a/adapter/context/param/methodparams_test.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2020 beego -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package param - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestMethodParamString(t *testing.T) { - method := New("myName", IsRequired, InHeader, Default("abc")) - s := method.String() - assert.Equal(t, `param.New("myName", param.IsRequired, param.InHeader, param.Default("abc"))`, s) -} - -func TestMake(t *testing.T) { - res := Make() - assert.Equal(t, 0, len(res)) - res = Make(New("myName", InBody)) - assert.Equal(t, 1, len(res)) -} diff --git a/adapter/context/param/options.go b/adapter/context/param/options.go deleted file mode 100644 index 1d9364c2..00000000 --- a/adapter/context/param/options.go +++ /dev/null @@ -1,45 +0,0 @@ -package param - -import ( - "github.com/beego/beego/v2/server/web/context/param" -) - -// MethodParamOption defines a func which apply options on a MethodParam -type MethodParamOption func(*MethodParam) - -// IsRequired indicates that this param is required and can not be omitted from the http request -var IsRequired MethodParamOption = func(p *MethodParam) { - param.IsRequired((*param.MethodParam)(p)) -} - -// InHeader indicates that this param is passed via an http header -var InHeader MethodParamOption = func(p *MethodParam) { - param.InHeader((*param.MethodParam)(p)) -} - -// InPath indicates that this param is part of the URL path -var InPath MethodParamOption = func(p *MethodParam) { - param.InPath((*param.MethodParam)(p)) -} - -// InBody indicates that this param is passed as an http request body -var InBody MethodParamOption = func(p *MethodParam) { - param.InBody((*param.MethodParam)(p)) -} - -// Default provides a default value for the http param -func Default(defaultValue interface{}) MethodParamOption { - return newMpoToOld(param.Default(defaultValue)) -} - -func newMpoToOld(n param.MethodParamOption) MethodParamOption { - return func(methodParam *MethodParam) { - n((*param.MethodParam)(methodParam)) - } -} - -func oldMpoToNew(old MethodParamOption) param.MethodParamOption { - return func(methodParam *param.MethodParam) { - old((*MethodParam)(methodParam)) - } -} diff --git a/adapter/context/renderer.go b/adapter/context/renderer.go deleted file mode 100644 index 2c5a53c1..00000000 --- a/adapter/context/renderer.go +++ /dev/null @@ -1,8 +0,0 @@ -package context - -import ( - "github.com/beego/beego/v2/server/web/context" -) - -// Renderer defines an http response renderer -type Renderer context.Renderer diff --git a/adapter/context/response.go b/adapter/context/response.go deleted file mode 100644 index 24e196a4..00000000 --- a/adapter/context/response.go +++ /dev/null @@ -1,26 +0,0 @@ -package context - -import ( - "net/http" - "strconv" -) - -const ( - // BadRequest indicates http error 400 - BadRequest StatusCode = http.StatusBadRequest - - // NotFound indicates http error 404 - NotFound StatusCode = http.StatusNotFound -) - -// StatusCode sets the http response status code -type StatusCode int - -func (s StatusCode) Error() string { - return strconv.Itoa(int(s)) -} - -// Render sets the http status code -func (s StatusCode) Render(ctx *Context) { - ctx.Output.SetStatus(int(s)) -} diff --git a/adapter/controller.go b/adapter/controller.go deleted file mode 100644 index 6d2d5f64..00000000 --- a/adapter/controller.go +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "mime/multipart" - "net/url" - - "github.com/beego/beego/v2/adapter/session" - "github.com/beego/beego/v2/server/web" - webContext "github.com/beego/beego/v2/server/web/context" -) - -var ( - // ErrAbort custom error when user stop request handler manually. - ErrAbort = web.ErrAbort - // GlobalControllerRouter store comments with controller. pkgpath+controller:comments - GlobalControllerRouter = web.GlobalControllerRouter -) - -// ControllerFilter store the filter for controller -type ControllerFilter web.ControllerFilter - -// ControllerFilterComments store the comment for controller level filter -type ControllerFilterComments web.ControllerFilterComments - -// ControllerImportComments store the import comment for controller needed -type ControllerImportComments web.ControllerImportComments - -// ControllerComments store the comment for the controller method -type ControllerComments web.ControllerComments - -// ControllerCommentsSlice implements the sort interface -type ControllerCommentsSlice web.ControllerCommentsSlice - -func (p ControllerCommentsSlice) Len() int { - return (web.ControllerCommentsSlice)(p).Len() -} - -func (p ControllerCommentsSlice) Less(i, j int) bool { - return (web.ControllerCommentsSlice)(p).Less(i, j) -} - -func (p ControllerCommentsSlice) Swap(i, j int) { - (web.ControllerCommentsSlice)(p).Swap(i, j) -} - -// Controller defines some basic http request handler operations, such as -// http context, template and view, session and xsrf. -type Controller web.Controller - -func (c *Controller) Init(ctx *webContext.Context, controllerName, actionName string, app interface{}) { - (*web.Controller)(c).Init(ctx, controllerName, actionName, app) -} - -// ControllerInterface is an interface to uniform all controller handler. -type ControllerInterface web.ControllerInterface - -// Prepare runs after Init before request function execution. -func (c *Controller) Prepare() { - (*web.Controller)(c).Prepare() -} - -// Finish runs after request function execution. -func (c *Controller) Finish() { - (*web.Controller)(c).Finish() -} - -// Get adds a request function to handle GET request. -func (c *Controller) Get() { - (*web.Controller)(c).Get() -} - -// Post adds a request function to handle POST request. -func (c *Controller) Post() { - (*web.Controller)(c).Post() -} - -// Delete adds a request function to handle DELETE request. -func (c *Controller) Delete() { - (*web.Controller)(c).Delete() -} - -// Put adds a request function to handle PUT request. -func (c *Controller) Put() { - (*web.Controller)(c).Put() -} - -// Head adds a request function to handle HEAD request. -func (c *Controller) Head() { - (*web.Controller)(c).Head() -} - -// Patch adds a request function to handle PATCH request. -func (c *Controller) Patch() { - (*web.Controller)(c).Patch() -} - -// Options adds a request function to handle OPTIONS request. -func (c *Controller) Options() { - (*web.Controller)(c).Options() -} - -// Trace adds a request function to handle Trace request. -// this method SHOULD NOT be overridden. -// https://tools.ietf.org/html/rfc7231#section-4.3.8 -// The TRACE method requests a remote, application-level loop-back of -// the request message. The final recipient of the request SHOULD -// reflect the message received, excluding some fields described below, -// back to the client as the message body of a 200 (OK) response with a -// Content-Type of "message/http" (Section 8.3.1 of [RFC7230]). -func (c *Controller) Trace() { - (*web.Controller)(c).Trace() -} - -// HandlerFunc call function with the name -func (c *Controller) HandlerFunc(fnname string) bool { - return (*web.Controller)(c).HandlerFunc(fnname) -} - -// URLMapping register the internal Controller router. -func (c *Controller) URLMapping() { - (*web.Controller)(c).URLMapping() -} - -// Mapping the method to function -func (c *Controller) Mapping(method string, fn func()) { - (*web.Controller)(c).Mapping(method, fn) -} - -// Render sends the response with rendered template bytes as text/html type. -func (c *Controller) Render() error { - return (*web.Controller)(c).Render() -} - -// RenderString returns the rendered template string. Do not send out response. -func (c *Controller) RenderString() (string, error) { - return (*web.Controller)(c).RenderString() -} - -// RenderBytes returns the bytes of rendered template string. Do not send out response. -func (c *Controller) RenderBytes() ([]byte, error) { - return (*web.Controller)(c).RenderBytes() -} - -// Redirect sends the redirection response to url with status code. -func (c *Controller) Redirect(url string, code int) { - (*web.Controller)(c).Redirect(url, code) -} - -// SetData set the data depending on the accepted -func (c *Controller) SetData(data interface{}) { - (*web.Controller)(c).SetData(data) -} - -// Abort stops controller handler and show the error data if code is defined in ErrorMap or code string. -func (c *Controller) Abort(code string) { - (*web.Controller)(c).Abort(code) -} - -// CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body. -func (c *Controller) CustomAbort(status int, body string) { - (*web.Controller)(c).CustomAbort(status, body) -} - -// StopRun makes panic of USERSTOPRUN error and go to recover function if defined. -func (c *Controller) StopRun() { - (*web.Controller)(c).StopRun() -} - -// URLFor does another controller handler in this request function. -// it goes to this controller method if endpoint is not clear. -func (c *Controller) URLFor(endpoint string, values ...interface{}) string { - return (*web.Controller)(c).URLFor(endpoint, values...) -} - -// ServeJSON sends a json response with encoding charset. -func (c *Controller) ServeJSON(encoding ...bool) { - (*web.Controller)(c).ServeJSON(encoding...) -} - -// ServeJSONP sends a jsonp response. -func (c *Controller) ServeJSONP() { - (*web.Controller)(c).ServeJSONP() -} - -// ServeXML sends xml response. -func (c *Controller) ServeXML() { - (*web.Controller)(c).ServeXML() -} - -// ServeYAML sends yaml response. -func (c *Controller) ServeYAML() { - (*web.Controller)(c).ServeYAML() -} - -// ServeFormatted serve YAML, XML OR JSON, depending on the value of the Accept header -func (c *Controller) ServeFormatted(encoding ...bool) { - (*web.Controller)(c).ServeFormatted(encoding...) -} - -// Input returns the input data map from POST or PUT request body and query string. -func (c *Controller) Input() url.Values { - val, _ := (*web.Controller)(c).Input() - return val -} - -// ParseForm maps input data map to obj struct. -func (c *Controller) ParseForm(obj interface{}) error { - return (*web.Controller)(c).ParseForm(obj) -} - -// GetString returns the input value by key string or the default value while it's present and input is blank -func (c *Controller) GetString(key string, def ...string) string { - return (*web.Controller)(c).GetString(key, def...) -} - -// GetStrings returns the input string slice by key string or the default value while it's present and input is blank -// it's designed for multi-value input field such as checkbox(input[type=checkbox]), multi-selection. -func (c *Controller) GetStrings(key string, def ...[]string) []string { - return (*web.Controller)(c).GetStrings(key, def...) -} - -// GetInt returns input as an int or the default value while it's present and input is blank -func (c *Controller) GetInt(key string, def ...int) (int, error) { - return (*web.Controller)(c).GetInt(key, def...) -} - -// GetInt8 return input as an int8 or the default value while it's present and input is blank -func (c *Controller) GetInt8(key string, def ...int8) (int8, error) { - return (*web.Controller)(c).GetInt8(key, def...) -} - -// GetUint8 return input as an uint8 or the default value while it's present and input is blank -func (c *Controller) GetUint8(key string, def ...uint8) (uint8, error) { - return (*web.Controller)(c).GetUint8(key, def...) -} - -// GetInt16 returns input as an int16 or the default value while it's present and input is blank -func (c *Controller) GetInt16(key string, def ...int16) (int16, error) { - return (*web.Controller)(c).GetInt16(key, def...) -} - -// GetUint16 returns input as an uint16 or the default value while it's present and input is blank -func (c *Controller) GetUint16(key string, def ...uint16) (uint16, error) { - return (*web.Controller)(c).GetUint16(key, def...) -} - -// GetInt32 returns input as an int32 or the default value while it's present and input is blank -func (c *Controller) GetInt32(key string, def ...int32) (int32, error) { - return (*web.Controller)(c).GetInt32(key, def...) -} - -// GetUint32 returns input as an uint32 or the default value while it's present and input is blank -func (c *Controller) GetUint32(key string, def ...uint32) (uint32, error) { - return (*web.Controller)(c).GetUint32(key, def...) -} - -// GetInt64 returns input value as int64 or the default value while it's present and input is blank. -func (c *Controller) GetInt64(key string, def ...int64) (int64, error) { - return (*web.Controller)(c).GetInt64(key, def...) -} - -// GetUint64 returns input value as uint64 or the default value while it's present and input is blank. -func (c *Controller) GetUint64(key string, def ...uint64) (uint64, error) { - return (*web.Controller)(c).GetUint64(key, def...) -} - -// GetBool returns input value as bool or the default value while it's present and input is blank. -func (c *Controller) GetBool(key string, def ...bool) (bool, error) { - return (*web.Controller)(c).GetBool(key, def...) -} - -// GetFloat returns input value as float64 or the default value while it's present and input is blank. -func (c *Controller) GetFloat(key string, def ...float64) (float64, error) { - return (*web.Controller)(c).GetFloat(key, def...) -} - -// GetFile returns the file data in file upload field named as key. -// it returns the first one of multi-uploaded files. -func (c *Controller) GetFile(key string) (multipart.File, *multipart.FileHeader, error) { - return (*web.Controller)(c).GetFile(key) -} - -// GetFiles return multi-upload files -// files, err:=c.GetFiles("myfiles") -// if err != nil { -// http.Error(w, err.Error(), http.StatusNoContent) -// return -// } -// for i, _ := range files { -// //for each fileheader, get a handle to the actual file -// file, err := files[i].Open() -// defer file.Close() -// if err != nil { -// http.Error(w, err.Error(), http.StatusInternalServerError) -// return -// } -// //create destination file making sure the path is writeable. -// dst, err := os.Create("upload/" + files[i].Filename) -// defer dst.Close() -// if err != nil { -// http.Error(w, err.Error(), http.StatusInternalServerError) -// return -// } -// //copy the uploaded file to the destination file -// if _, err := io.Copy(dst, file); err != nil { -// http.Error(w, err.Error(), http.StatusInternalServerError) -// return -// } -// } -func (c *Controller) GetFiles(key string) ([]*multipart.FileHeader, error) { - return (*web.Controller)(c).GetFiles(key) -} - -// SaveToFile saves uploaded file to new path. -// it only operates the first one of mutil-upload form file field. -func (c *Controller) SaveToFile(fromfile, tofile string) error { - return (*web.Controller)(c).SaveToFile(fromfile, tofile) -} - -// StartSession starts session and load old session data info this controller. -func (c *Controller) StartSession() session.Store { - s := (*web.Controller)(c).StartSession() - return session.CreateNewToOldStoreAdapter(s) -} - -// SetSession puts value into session. -func (c *Controller) SetSession(name interface{}, value interface{}) { - (*web.Controller)(c).SetSession(name, value) -} - -// GetSession gets value from session. -func (c *Controller) GetSession(name interface{}) interface{} { - return (*web.Controller)(c).GetSession(name) -} - -// DelSession removes value from session. -func (c *Controller) DelSession(name interface{}) { - (*web.Controller)(c).DelSession(name) -} - -// SessionRegenerateID regenerates session id for this session. -// the session data have no changes. -func (c *Controller) SessionRegenerateID() { - (*web.Controller)(c).SessionRegenerateID() -} - -// DestroySession cleans session data and session cookie. -func (c *Controller) DestroySession() { - (*web.Controller)(c).DestroySession() -} - -// IsAjax returns this request is ajax or not. -func (c *Controller) IsAjax() bool { - return (*web.Controller)(c).IsAjax() -} - -// GetSecureCookie returns decoded cookie value from encoded browser cookie values. -func (c *Controller) GetSecureCookie(Secret, key string) (string, bool) { - return (*web.Controller)(c).GetSecureCookie(Secret, key) -} - -// SetSecureCookie puts value into cookie after encoded the value. -func (c *Controller) SetSecureCookie(Secret, name, value string, others ...interface{}) { - (*web.Controller)(c).SetSecureCookie(Secret, name, value, others...) -} - -// XSRFToken creates a CSRF token string and returns. -func (c *Controller) XSRFToken() string { - return (*web.Controller)(c).XSRFToken() -} - -// CheckXSRFCookie checks xsrf token in this request is valid or not. -// the token can provided in request header "X-Xsrftoken" and "X-CsrfToken" -// or in form field value named as "_xsrf". -func (c *Controller) CheckXSRFCookie() bool { - return (*web.Controller)(c).CheckXSRFCookie() -} - -// XSRFFormHTML writes an input field contains xsrf token value. -func (c *Controller) XSRFFormHTML() string { - return (*web.Controller)(c).XSRFFormHTML() -} - -// GetControllerAndAction gets the executing controller name and action name. -func (c *Controller) GetControllerAndAction() (string, string) { - return (*web.Controller)(c).GetControllerAndAction() -} diff --git a/adapter/doc.go b/adapter/doc.go deleted file mode 100644 index ef4bdffd..00000000 --- a/adapter/doc.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2020 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package adapter used to keep compatible with v1.x -package adapter diff --git a/adapter/error.go b/adapter/error.go deleted file mode 100644 index 67f2ab82..00000000 --- a/adapter/error.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "net/http" - - "github.com/beego/beego/v2/adapter/context" - "github.com/beego/beego/v2/server/web" - beecontext "github.com/beego/beego/v2/server/web/context" -) - -const ( - errorTypeHandler = iota - errorTypeController -) - -var tpl = ` - - - - - beego application error - - - - - -
- - - - - - - - - - -
Request Method: {{.RequestMethod}}
Request URL: {{.RequestURL}}
RemoteAddr: {{.RemoteAddr }}
-
- Stack -
{{.Stack}}
-
-
- - - -` - -var errtpl = ` - - - - - {{.Title}} - - - -
-
- -
- {{.Content}} - Go Home
- -
Powered by beego {{.BeegoVersion}} -
-
-
- - -` - -// ErrorMaps holds map of http handlers for each error string. -// there is 10 kinds default error(40x and 50x) -var ErrorMaps = web.ErrorMaps - -// ErrorHandler registers http.HandlerFunc to each http err code string. -// usage: -// beego.ErrorHandler("404",NotFound) -// beego.ErrorHandler("500",InternalServerError) -func ErrorHandler(code string, h http.HandlerFunc) *App { - return (*App)(web.ErrorHandler(code, h)) -} - -// ErrorController registers ControllerInterface to each http err code string. -// usage: -// beego.ErrorController(&controllers.ErrorController{}) -func ErrorController(c ControllerInterface) *App { - return (*App)(web.ErrorController(c)) -} - -// Exception Write HttpStatus with errCode and Exec error handler if exist. -func Exception(errCode uint64, ctx *context.Context) { - web.Exception(errCode, (*beecontext.Context)(ctx)) -} diff --git a/adapter/filter.go b/adapter/filter.go deleted file mode 100644 index 660193b9..00000000 --- a/adapter/filter.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "github.com/beego/beego/v2/adapter/context" - "github.com/beego/beego/v2/server/web" - beecontext "github.com/beego/beego/v2/server/web/context" -) - -// FilterFunc defines a filter function which is invoked before the controller handler is executed. -type FilterFunc func(*context.Context) - -// FilterRouter defines a filter operation which is invoked before the controller handler is executed. -// It can match the URL against a pattern, and execute a filter function -// when a request with a matching URL arrives. -type FilterRouter web.FilterRouter - -// ValidRouter checks if the current request is matched by this filter. -// If the request is matched, the values of the URL parameters defined -// by the filter pattern are also returned. -func (f *FilterRouter) ValidRouter(url string, ctx *context.Context) bool { - return (*web.FilterRouter)(f).ValidRouter(url, (*beecontext.Context)(ctx)) -} diff --git a/adapter/flash.go b/adapter/flash.go deleted file mode 100644 index aab9b3ce..00000000 --- a/adapter/flash.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "github.com/beego/beego/v2/server/web" -) - -// FlashData is a tools to maintain data when using across request. -type FlashData web.FlashData - -// NewFlash return a new empty FlashData struct. -func NewFlash() *FlashData { - return (*FlashData)(web.NewFlash()) -} - -// Set message to flash -func (fd *FlashData) Set(key string, msg string, args ...interface{}) { - (*web.FlashData)(fd).Set(key, msg, args...) -} - -// Success writes success message to flash. -func (fd *FlashData) Success(msg string, args ...interface{}) { - (*web.FlashData)(fd).Success(msg, args...) -} - -// Notice writes notice message to flash. -func (fd *FlashData) Notice(msg string, args ...interface{}) { - (*web.FlashData)(fd).Notice(msg, args...) -} - -// Warning writes warning message to flash. -func (fd *FlashData) Warning(msg string, args ...interface{}) { - (*web.FlashData)(fd).Warning(msg, args...) -} - -// Error writes error message to flash. -func (fd *FlashData) Error(msg string, args ...interface{}) { - (*web.FlashData)(fd).Error(msg, args...) -} - -// Store does the saving operation of flash data. -// the data are encoded and saved in cookie. -func (fd *FlashData) Store(c *Controller) { - (*web.FlashData)(fd).Store((*web.Controller)(c)) -} - -// ReadFromRequest parsed flash data from encoded values in cookie. -func ReadFromRequest(c *Controller) *FlashData { - return (*FlashData)(web.ReadFromRequest((*web.Controller)(c))) -} diff --git a/adapter/fs.go b/adapter/fs.go deleted file mode 100644 index 168e312a..00000000 --- a/adapter/fs.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "net/http" - "path/filepath" - - "github.com/beego/beego/v2/server/web" -) - -type FileSystem web.FileSystem - -func (d FileSystem) Open(name string) (http.File, error) { - return (web.FileSystem)(d).Open(name) -} - -// Walk walks the file tree rooted at root in filesystem, calling walkFn for each file or -// directory in the tree, including root. All errors that arise visiting files -// and directories are filtered by walkFn. -func Walk(fs http.FileSystem, root string, walkFn filepath.WalkFunc) error { - return web.Walk(fs, root, walkFn) -} diff --git a/adapter/grace/grace.go b/adapter/grace/grace.go deleted file mode 100644 index de047eb1..00000000 --- a/adapter/grace/grace.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package grace use to hot reload -// Description: http://grisha.org/blog/2014/06/03/graceful-restart-in-golang/ -// -// Usage: -// -// import( -// "log" -// "net/http" -// "os" -// -// "github.com/beego/beego/v2/server/web/grace" -// ) -// -// func handler(w http.ResponseWriter, r *http.Request) { -// w.Write([]byte("WORLD!")) -// } -// -// func main() { -// mux := http.NewServeMux() -// mux.HandleFunc("/hello", handler) -// -// err := grace.ListenAndServe("localhost:8080", mux) -// if err != nil { -// log.Println(err) -// } -// log.Println("Server on 8080 stopped") -// os.Exit(0) -// } -package grace - -import ( - "net/http" - "time" - - "github.com/beego/beego/v2/server/web/grace" -) - -const ( - // PreSignal is the position to add filter before signal - PreSignal = iota - // PostSignal is the position to add filter after signal - PostSignal - // StateInit represent the application inited - StateInit - // StateRunning represent the application is running - StateRunning - // StateShuttingDown represent the application is shutting down - StateShuttingDown - // StateTerminate represent the application is killed - StateTerminate -) - -var ( - - // DefaultReadTimeOut is the HTTP read timeout - DefaultReadTimeOut time.Duration - // DefaultWriteTimeOut is the HTTP Write timeout - DefaultWriteTimeOut time.Duration - // DefaultMaxHeaderBytes is the Max HTTP Header size, default is 0, no limit - DefaultMaxHeaderBytes int - // DefaultTimeout is the shutdown server's timeout. default is 60s - DefaultTimeout = grace.DefaultTimeout -) - -// NewServer returns a new graceServer. -func NewServer(addr string, handler http.Handler) (srv *Server) { - return (*Server)(grace.NewServer(addr, handler)) -} - -// ListenAndServe refer http.ListenAndServe -func ListenAndServe(addr string, handler http.Handler) error { - server := NewServer(addr, handler) - return server.ListenAndServe() -} - -// ListenAndServeTLS refer http.ListenAndServeTLS -func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error { - server := NewServer(addr, handler) - return server.ListenAndServeTLS(certFile, keyFile) -} diff --git a/adapter/grace/server.go b/adapter/grace/server.go deleted file mode 100644 index 95ca05b4..00000000 --- a/adapter/grace/server.go +++ /dev/null @@ -1,48 +0,0 @@ -package grace - -import ( - "os" - - "github.com/beego/beego/v2/server/web/grace" -) - -// Server embedded http.Server -type Server grace.Server - -// Serve accepts incoming connections on the Listener l, -// creating a new service goroutine for each. -// The service goroutines read requests and then call srv.Handler to reply to them. -func (srv *Server) Serve() (err error) { - return (*grace.Server)(srv).Serve() -} - -// ListenAndServe listens on the TCP network address srv.Addr and then calls Serve -// to handle requests on incoming connections. If srv.Addr is blank, ":http" is -// used. -func (srv *Server) ListenAndServe() (err error) { - return (*grace.Server)(srv).ListenAndServe() -} - -// ListenAndServeTLS listens on the TCP network address srv.Addr and then calls -// Serve to handle requests on incoming TLS connections. -// -// Filenames containing a certificate and matching private key for the server must -// be provided. If the certificate is signed by a certificate authority, the -// certFile should be the concatenation of the server's certificate followed by the -// CA's certificate. -// -// If srv.Addr is blank, ":https" is used. -func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { - return (*grace.Server)(srv).ListenAndServeTLS(certFile, keyFile) -} - -// ListenAndServeMutualTLS listens on the TCP network address srv.Addr and then calls -// Serve to handle requests on incoming mutual TLS connections. -func (srv *Server) ListenAndServeMutualTLS(certFile, keyFile, trustFile string) error { - return (*grace.Server)(srv).ListenAndServeMutualTLS(certFile, keyFile, trustFile) -} - -// RegisterSignalHook registers a function to be run PreSignal or PostSignal for a given signal. -func (srv *Server) RegisterSignalHook(ppFlag int, sig os.Signal, f func()) error { - return (*grace.Server)(srv).RegisterSignalHook(ppFlag, sig, f) -} diff --git a/adapter/httplib/httplib.go b/adapter/httplib/httplib.go deleted file mode 100644 index 9b0cfe26..00000000 --- a/adapter/httplib/httplib.go +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package httplib is used as http.Client -// Usage: -// -// import "github.com/beego/beego/v2/client/httplib" -// -// b := httplib.Post("http://beego.vip/") -// b.Param("username","astaxie") -// b.Param("password","123456") -// b.PostFile("uploadfile1", "httplib.pdf") -// b.PostFile("uploadfile2", "httplib.txt") -// str, err := b.String() -// if err != nil { -// t.Fatal(err) -// } -// fmt.Println(str) -// -package httplib - -import ( - "crypto/tls" - "net" - "net/http" - "net/url" - "time" - - "github.com/beego/beego/v2/client/httplib" -) - -// SetDefaultSetting Overwrite default settings -func SetDefaultSetting(setting BeegoHTTPSettings) { - httplib.SetDefaultSetting(httplib.BeegoHTTPSettings(setting)) -} - -// NewBeegoRequest return *BeegoHttpRequest with specific method -func NewBeegoRequest(rawurl, method string) *BeegoHTTPRequest { - return &BeegoHTTPRequest{ - delegate: httplib.NewBeegoRequest(rawurl, method), - } -} - -// Get returns *BeegoHttpRequest with GET method. -func Get(url string) *BeegoHTTPRequest { - return NewBeegoRequest(url, "GET") -} - -// Post returns *BeegoHttpRequest with POST method. -func Post(url string) *BeegoHTTPRequest { - return NewBeegoRequest(url, "POST") -} - -// Put returns *BeegoHttpRequest with PUT method. -func Put(url string) *BeegoHTTPRequest { - return NewBeegoRequest(url, "PUT") -} - -// Delete returns *BeegoHttpRequest DELETE method. -func Delete(url string) *BeegoHTTPRequest { - return NewBeegoRequest(url, "DELETE") -} - -// Head returns *BeegoHttpRequest with HEAD method. -func Head(url string) *BeegoHTTPRequest { - return NewBeegoRequest(url, "HEAD") -} - -// BeegoHTTPSettings is the http.Client setting -type BeegoHTTPSettings httplib.BeegoHTTPSettings - -// BeegoHTTPRequest provides more useful methods for requesting one url than http.Request. -type BeegoHTTPRequest struct { - delegate *httplib.BeegoHTTPRequest -} - -// GetRequest return the request object -func (b *BeegoHTTPRequest) GetRequest() *http.Request { - return b.delegate.GetRequest() -} - -// Setting Change request settings -func (b *BeegoHTTPRequest) Setting(setting BeegoHTTPSettings) *BeegoHTTPRequest { - b.delegate.Setting(httplib.BeegoHTTPSettings(setting)) - return b -} - -// SetBasicAuth sets the request's Authorization header to use HTTP Basic Authentication with the provided username and password. -func (b *BeegoHTTPRequest) SetBasicAuth(username, password string) *BeegoHTTPRequest { - b.delegate.SetBasicAuth(username, password) - return b -} - -// SetEnableCookie sets enable/disable cookiejar -func (b *BeegoHTTPRequest) SetEnableCookie(enable bool) *BeegoHTTPRequest { - b.delegate.SetEnableCookie(enable) - return b -} - -// SetUserAgent sets User-Agent header field -func (b *BeegoHTTPRequest) SetUserAgent(useragent string) *BeegoHTTPRequest { - b.delegate.SetUserAgent(useragent) - return b -} - -// Retries sets Retries times. -// default is 0 means no retried. -// -1 means retried forever. -// others means retried times. -func (b *BeegoHTTPRequest) Retries(times int) *BeegoHTTPRequest { - b.delegate.Retries(times) - return b -} - -func (b *BeegoHTTPRequest) RetryDelay(delay time.Duration) *BeegoHTTPRequest { - b.delegate.RetryDelay(delay) - return b -} - -// SetTimeout sets connect time out and read-write time out for BeegoRequest. -func (b *BeegoHTTPRequest) SetTimeout(connectTimeout, readWriteTimeout time.Duration) *BeegoHTTPRequest { - b.delegate.SetTimeout(connectTimeout, readWriteTimeout) - return b -} - -// SetTLSClientConfig sets tls connection configurations if visiting https url. -func (b *BeegoHTTPRequest) SetTLSClientConfig(config *tls.Config) *BeegoHTTPRequest { - b.delegate.SetTLSClientConfig(config) - return b -} - -// Header add header item string in request. -func (b *BeegoHTTPRequest) Header(key, value string) *BeegoHTTPRequest { - b.delegate.Header(key, value) - return b -} - -// SetHost set the request host -func (b *BeegoHTTPRequest) SetHost(host string) *BeegoHTTPRequest { - b.delegate.SetHost(host) - return b -} - -// SetProtocolVersion Set the protocol version for incoming requests. -// Client requests always use HTTP/1.1. -func (b *BeegoHTTPRequest) SetProtocolVersion(vers string) *BeegoHTTPRequest { - b.delegate.SetProtocolVersion(vers) - return b -} - -// SetCookie add cookie into request. -func (b *BeegoHTTPRequest) SetCookie(cookie *http.Cookie) *BeegoHTTPRequest { - b.delegate.SetCookie(cookie) - return b -} - -// SetTransport set the setting transport -func (b *BeegoHTTPRequest) SetTransport(transport http.RoundTripper) *BeegoHTTPRequest { - b.delegate.SetTransport(transport) - return b -} - -// SetProxy set the http proxy -// example: -// -// func(req *http.Request) (*url.URL, error) { -// u, _ := url.ParseRequestURI("http://127.0.0.1:8118") -// return u, nil -// } -func (b *BeegoHTTPRequest) SetProxy(proxy func(*http.Request) (*url.URL, error)) *BeegoHTTPRequest { - b.delegate.SetProxy(proxy) - return b -} - -// SetCheckRedirect specifies the policy for handling redirects. -// -// If CheckRedirect is nil, the Client uses its default policy, -// which is to stop after 10 consecutive requests. -func (b *BeegoHTTPRequest) SetCheckRedirect(redirect func(req *http.Request, via []*http.Request) error) *BeegoHTTPRequest { - b.delegate.SetCheckRedirect(redirect) - return b -} - -// Param adds query param in to request. -// params build query string as ?key1=value1&key2=value2... -func (b *BeegoHTTPRequest) Param(key, value string) *BeegoHTTPRequest { - b.delegate.Param(key, value) - return b -} - -// PostFile add a post file to the request -func (b *BeegoHTTPRequest) PostFile(formname, filename string) *BeegoHTTPRequest { - b.delegate.PostFile(formname, filename) - return b -} - -// Body adds request raw body. -// it supports string and []byte. -func (b *BeegoHTTPRequest) Body(data interface{}) *BeegoHTTPRequest { - b.delegate.Body(data) - return b -} - -// XMLBody adds request raw body encoding by XML. -func (b *BeegoHTTPRequest) XMLBody(obj interface{}) (*BeegoHTTPRequest, error) { - _, err := b.delegate.XMLBody(obj) - return b, err -} - -// YAMLBody adds request raw body encoding by YAML. -func (b *BeegoHTTPRequest) YAMLBody(obj interface{}) (*BeegoHTTPRequest, error) { - _, err := b.delegate.YAMLBody(obj) - return b, err -} - -// JSONBody adds request raw body encoding by JSON. -func (b *BeegoHTTPRequest) JSONBody(obj interface{}) (*BeegoHTTPRequest, error) { - _, err := b.delegate.JSONBody(obj) - return b, err -} - -// DoRequest will do the client.Do -func (b *BeegoHTTPRequest) DoRequest() (resp *http.Response, err error) { - return b.delegate.DoRequest() -} - -// String returns the body string in response. -// it calls Response inner. -func (b *BeegoHTTPRequest) String() (string, error) { - return b.delegate.String() -} - -// Bytes returns the body []byte in response. -// it calls Response inner. -func (b *BeegoHTTPRequest) Bytes() ([]byte, error) { - return b.delegate.Bytes() -} - -// ToFile saves the body data in response to one file. -// it calls Response inner. -func (b *BeegoHTTPRequest) ToFile(filename string) error { - return b.delegate.ToFile(filename) -} - -// ToJSON returns the map that marshals from the body bytes as json in response . -// it calls Response inner. -func (b *BeegoHTTPRequest) ToJSON(v interface{}) error { - return b.delegate.ToJSON(v) -} - -// ToXML returns the map that marshals from the body bytes as xml in response . -// it calls Response inner. -func (b *BeegoHTTPRequest) ToXML(v interface{}) error { - return b.delegate.ToXML(v) -} - -// ToYAML returns the map that marshals from the body bytes as yaml in response . -// it calls Response inner. -func (b *BeegoHTTPRequest) ToYAML(v interface{}) error { - return b.delegate.ToYAML(v) -} - -// Response executes request client gets response mannually. -func (b *BeegoHTTPRequest) Response() (*http.Response, error) { - return b.delegate.Response() -} - -// TimeoutDialer returns functions of connection dialer with timeout settings for http.Transport Dial field. -func TimeoutDialer(cTimeout time.Duration, rwTimeout time.Duration) func(net, addr string) (c net.Conn, err error) { - return httplib.TimeoutDialer(cTimeout, rwTimeout) -} diff --git a/adapter/httplib/httplib_test.go b/adapter/httplib/httplib_test.go deleted file mode 100644 index 41018c19..00000000 --- a/adapter/httplib/httplib_test.go +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package httplib - -import ( - "bytes" - "errors" - "io/ioutil" - "net" - "net/http" - "os" - "strings" - "testing" - "time" -) - -const ( - getURL = "http://httpbin.org/get" - ipURL = "http://httpbin.org/ip" -) - -func TestResponse(t *testing.T) { - req := Get(getURL) - resp, err := req.Response() - if err != nil { - t.Fatal(err) - } - t.Log(resp) -} - -func TestDoRequest(t *testing.T) { - req := Get("https://goolnk.com/33BD2j") - retryAmount := 1 - req.Retries(1) - req.RetryDelay(1400 * time.Millisecond) - retryDelay := 1400 * time.Millisecond - - req.SetCheckRedirect(func(redirectReq *http.Request, redirectVia []*http.Request) error { - return errors.New("Redirect triggered") - }) - - startTime := time.Now().UnixNano() / int64(time.Millisecond) - - _, err := req.Response() - if err == nil { - t.Fatal("Response should have yielded an error") - } - - endTime := time.Now().UnixNano() / int64(time.Millisecond) - elapsedTime := endTime - startTime - delayedTime := int64(retryAmount) * retryDelay.Milliseconds() - - if elapsedTime < delayedTime { - t.Errorf("Not enough retries. Took %dms. Delay was meant to take %dms", elapsedTime, delayedTime) - } -} - -func TestGet(t *testing.T) { - req := Get(getURL) - b, err := req.Bytes() - if err != nil { - t.Fatal(err) - } - t.Log(b) - - s, err := req.String() - if err != nil { - t.Fatal(err) - } - t.Log(s) - - if string(b) != s { - t.Fatal("request data not match") - } -} - -func TestSimplePost(t *testing.T) { - v := "smallfish" - req := Post("http://httpbin.org/post") - req.Param("username", v) - - str, err := req.String() - if err != nil { - t.Fatal(err) - } - t.Log(str) - - n := strings.Index(str, v) - if n == -1 { - t.Fatal(v + " not found in post") - } -} - -// func TestPostFile(t *testing.T) { -// v := "smallfish" -// req := Post("http://httpbin.org/post") -// req.Debug(true) -// req.Param("username", v) -// req.PostFile("uploadfile", "httplib_test.go") - -// str, err := req.String() -// if err != nil { -// t.Fatal(err) -// } -// t.Log(str) - -// n := strings.Index(str, v) -// if n == -1 { -// t.Fatal(v + " not found in post") -// } -// } - -func TestSimplePut(t *testing.T) { - str, err := Put("http://httpbin.org/put").String() - if err != nil { - t.Fatal(err) - } - t.Log(str) -} - -func TestSimpleDelete(t *testing.T) { - str, err := Delete("http://httpbin.org/delete").String() - if err != nil { - t.Fatal(err) - } - t.Log(str) -} - -func TestSimpleDeleteParam(t *testing.T) { - str, err := Delete("http://httpbin.org/delete").Param("key", "val").String() - if err != nil { - t.Fatal(err) - } - t.Log(str) -} - -func TestWithCookie(t *testing.T) { - v := "smallfish" - str, err := Get("http://httpbin.org/cookies/set?k1=" + v).SetEnableCookie(true).String() - if err != nil { - t.Fatal(err) - } - t.Log(str) - - str, err = Get("http://httpbin.org/cookies").SetEnableCookie(true).String() - if err != nil { - t.Fatal(err) - } - t.Log(str) - - n := strings.Index(str, v) - if n == -1 { - t.Fatal(v + " not found in cookie") - } -} - -func TestWithBasicAuth(t *testing.T) { - str, err := Get("http://httpbin.org/basic-auth/user/passwd").SetBasicAuth("user", "passwd").String() - if err != nil { - t.Fatal(err) - } - t.Log(str) - n := strings.Index(str, "authenticated") - if n == -1 { - t.Fatal("authenticated not found in response") - } -} - -func TestWithUserAgent(t *testing.T) { - v := "beego" - str, err := Get("http://httpbin.org/headers").SetUserAgent(v).String() - if err != nil { - t.Fatal(err) - } - t.Log(str) - - n := strings.Index(str, v) - if n == -1 { - t.Fatal(v + " not found in user-agent") - } -} - -func TestWithSetting(t *testing.T) { - v := "beego" - var setting BeegoHTTPSettings - setting.EnableCookie = true - setting.UserAgent = v - setting.Transport = &http.Transport{ - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, - }).DialContext, - MaxIdleConns: 50, - IdleConnTimeout: 90 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - } - setting.ReadWriteTimeout = 5 * time.Second - SetDefaultSetting(setting) - - str, err := Get(getURL).String() - if err != nil { - t.Fatal(err) - } - t.Log(str) - - n := strings.Index(str, v) - if n == -1 { - t.Fatal(v + " not found in user-agent") - } -} - -func TestToJson(t *testing.T) { - req := Get(ipURL) - resp, err := req.Response() - if err != nil { - t.Fatal(err) - } - t.Log(resp) - - // httpbin will return http remote addr - type IP struct { - Origin string `json:"origin"` - } - var ip IP - err = req.ToJSON(&ip) - if err != nil { - t.Fatal(err) - } - t.Log(ip.Origin) - ips := strings.Split(ip.Origin, ",") - if len(ips) == 0 { - t.Fatal("response is not valid ip") - } - for i := range ips { - if net.ParseIP(strings.TrimSpace(ips[i])).To4() == nil { - t.Fatal("response is not valid ip") - } - } -} - -func TestToFile(t *testing.T) { - f := "beego_testfile" - req := Get(ipURL) - err := req.ToFile(f) - if err != nil { - t.Fatal(err) - } - defer os.Remove(f) - b, err := ioutil.ReadFile(f) - if n := bytes.Index(b, []byte("origin")); n == -1 { - t.Fatal(err) - } -} - -func TestToFileDir(t *testing.T) { - f := "./files/beego_testfile" - req := Get(ipURL) - err := req.ToFile(f) - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll("./files") - b, err := ioutil.ReadFile(f) - if n := bytes.Index(b, []byte("origin")); n == -1 { - t.Fatal(err) - } -} - -func TestHeader(t *testing.T) { - req := Get("http://httpbin.org/headers") - req.Header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36") - str, err := req.String() - if err != nil { - t.Fatal(err) - } - t.Log(str) -} diff --git a/adapter/log.go b/adapter/log.go deleted file mode 100644 index 9fc3a551..00000000 --- a/adapter/log.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "strings" - - "github.com/beego/beego/v2/core/logs" -) - -// Log levels to control the logging output. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -const ( - LevelEmergency = logs.LevelEmergency - LevelAlert = logs.LevelAlert - LevelCritical = logs.LevelCritical - LevelError = logs.LevelError - LevelWarning = logs.LevelWarning - LevelNotice = logs.LevelNotice - LevelInformational = logs.LevelInformational - LevelDebug = logs.LevelDebug -) - -// BeeLogger references the used application logger. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -var BeeLogger = logs.GetBeeLogger() - -// SetLevel sets the global log level used by the simple logger. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func SetLevel(l int) { - logs.SetLevel(l) -} - -// SetLogFuncCall set the CallDepth, default is 3 -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func SetLogFuncCall(b bool) { - logs.SetLogFuncCall(b) -} - -// SetLogger sets a new logger. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func SetLogger(adaptername string, config string) error { - return logs.SetLogger(adaptername, config) -} - -// Emergency logs a message at emergency level. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Emergency(v ...interface{}) { - logs.Emergency(generateFmtStr(len(v)), v...) -} - -// Alert logs a message at alert level. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Alert(v ...interface{}) { - logs.Alert(generateFmtStr(len(v)), v...) -} - -// Critical logs a message at critical level. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Critical(v ...interface{}) { - logs.Critical(generateFmtStr(len(v)), v...) -} - -// Error logs a message at error level. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Error(v ...interface{}) { - logs.Error(generateFmtStr(len(v)), v...) -} - -// Warning logs a message at warning level. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Warning(v ...interface{}) { - logs.Warning(generateFmtStr(len(v)), v...) -} - -// Warn compatibility alias for Warning() -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Warn(v ...interface{}) { - logs.Warn(generateFmtStr(len(v)), v...) -} - -// Notice logs a message at notice level. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Notice(v ...interface{}) { - logs.Notice(generateFmtStr(len(v)), v...) -} - -// Informational logs a message at info level. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Informational(v ...interface{}) { - logs.Informational(generateFmtStr(len(v)), v...) -} - -// Info compatibility alias for Warning() -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Info(v ...interface{}) { - logs.Info(generateFmtStr(len(v)), v...) -} - -// Debug logs a message at debug level. -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Debug(v ...interface{}) { - logs.Debug(generateFmtStr(len(v)), v...) -} - -// Trace logs a message at trace level. -// compatibility alias for Warning() -// Deprecated: use github.com/beego/beego/v2/core/logs instead. -func Trace(v ...interface{}) { - logs.Trace(generateFmtStr(len(v)), v...) -} - -func generateFmtStr(n int) string { - return strings.Repeat("%v ", n) -} diff --git a/adapter/logs/accesslog.go b/adapter/logs/accesslog.go deleted file mode 100644 index f4370a5d..00000000 --- a/adapter/logs/accesslog.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package logs - -import ( - "github.com/beego/beego/v2/core/logs" -) - -// AccessLogRecord struct for holding access log data. -type AccessLogRecord logs.AccessLogRecord - -// AccessLog - Format and print access log. -func AccessLog(r *AccessLogRecord, format string) { - logs.AccessLog((*logs.AccessLogRecord)(r), format) -} diff --git a/adapter/logs/alils/alils.go b/adapter/logs/alils/alils.go deleted file mode 100644 index 2f700457..00000000 --- a/adapter/logs/alils/alils.go +++ /dev/null @@ -1,5 +0,0 @@ -package alils - -import ( - _ "github.com/beego/beego/v2/core/logs/alils" -) diff --git a/adapter/logs/es/es.go b/adapter/logs/es/es.go deleted file mode 100644 index 124e3fdd..00000000 --- a/adapter/logs/es/es.go +++ /dev/null @@ -1,5 +0,0 @@ -package es - -import ( - _ "github.com/beego/beego/v2/core/logs/es" -) diff --git a/adapter/logs/log.go b/adapter/logs/log.go deleted file mode 100644 index a040a1f5..00000000 --- a/adapter/logs/log.go +++ /dev/null @@ -1,346 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package logs provide a general log interface -// Usage: -// -// import "github.com/beego/beego/v2/core/logs" -// -// log := NewLogger(10000) -// log.SetLogger("console", "") -// -// > the first params stand for how many channel -// -// Use it like this: -// -// log.Trace("trace") -// log.Info("info") -// log.Warn("warning") -// log.Debug("debug") -// log.Critical("critical") -// -package logs - -import ( - "log" - "time" - - "github.com/beego/beego/v2/core/logs" -) - -// RFC5424 log message levels. -const ( - LevelEmergency = iota - LevelAlert - LevelCritical - LevelError - LevelWarning - LevelNotice - LevelInformational - LevelDebug -) - -// levelLogLogger is defined to implement log.Logger -// the real log level will be LevelEmergency -const levelLoggerImpl = -1 - -// Name for adapter with beego official support -const ( - AdapterConsole = "console" - AdapterFile = "file" - AdapterMultiFile = "multifile" - AdapterMail = "smtp" - AdapterConn = "conn" - AdapterEs = "es" - AdapterJianLiao = "jianliao" - AdapterSlack = "slack" - AdapterAliLS = "alils" -) - -// Legacy log level constants to ensure backwards compatibility. -const ( - LevelInfo = LevelInformational - LevelTrace = LevelDebug - LevelWarn = LevelWarning -) - -type newLoggerFunc func() Logger - -// Logger defines the behavior of a log provider. -type Logger interface { - Init(config string) error - WriteMsg(when time.Time, msg string, level int) error - Destroy() - Flush() -} - -// Register makes a log provide available by the provided name. -// If Register is called twice with the same name or if driver is nil, -// it panics. -func Register(name string, log newLoggerFunc) { - logs.Register(name, func() logs.Logger { - return &oldToNewAdapter{ - old: log(), - } - }) -} - -// BeeLogger is default logger in beego application. -// it can contain several providers and log message into all providers. -type BeeLogger logs.BeeLogger - -const defaultAsyncMsgLen = 1e3 - -// NewLogger returns a new BeeLogger. -// channelLen means the number of messages in chan(used where asynchronous is true). -// if the buffering chan is full, logger adapters write to file or other way. -func NewLogger(channelLens ...int64) *BeeLogger { - return (*BeeLogger)(logs.NewLogger(channelLens...)) -} - -// Async set the log to asynchronous and start the goroutine -func (bl *BeeLogger) Async(msgLen ...int64) *BeeLogger { - (*logs.BeeLogger)(bl).Async(msgLen...) - return bl -} - -// SetLogger provides a given logger adapter into BeeLogger with config string. -// config need to be correct JSON as string: {"interval":360}. -func (bl *BeeLogger) SetLogger(adapterName string, configs ...string) error { - return (*logs.BeeLogger)(bl).SetLogger(adapterName, configs...) -} - -// DelLogger remove a logger adapter in BeeLogger. -func (bl *BeeLogger) DelLogger(adapterName string) error { - return (*logs.BeeLogger)(bl).DelLogger(adapterName) -} - -func (bl *BeeLogger) Write(p []byte) (n int, err error) { - return (*logs.BeeLogger)(bl).Write(p) -} - -// SetLevel Set log message level. -// If message level (such as LevelDebug) is higher than logger level (such as LevelWarning), -// log providers will not even be sent the message. -func (bl *BeeLogger) SetLevel(l int) { - (*logs.BeeLogger)(bl).SetLevel(l) -} - -// GetLevel Get Current log message level. -func (bl *BeeLogger) GetLevel() int { - return (*logs.BeeLogger)(bl).GetLevel() -} - -// SetLogFuncCallDepth set log funcCallDepth -func (bl *BeeLogger) SetLogFuncCallDepth(d int) { - (*logs.BeeLogger)(bl).SetLogFuncCallDepth(d) -} - -// GetLogFuncCallDepth return log funcCallDepth for wrapper -func (bl *BeeLogger) GetLogFuncCallDepth() int { - return (*logs.BeeLogger)(bl).GetLogFuncCallDepth() -} - -// EnableFuncCallDepth enable log funcCallDepth -func (bl *BeeLogger) EnableFuncCallDepth(b bool) { - (*logs.BeeLogger)(bl).EnableFuncCallDepth(b) -} - -// SetPrefix will set prefix -func (bl *BeeLogger) SetPrefix(s string) { - (*logs.BeeLogger)(bl).SetPrefix(s) -} - -// Emergency Log EMERGENCY level message. -func (bl *BeeLogger) Emergency(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Emergency(format, v...) -} - -// Alert Log ALERT level message. -func (bl *BeeLogger) Alert(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Alert(format, v...) -} - -// Critical Log CRITICAL level message. -func (bl *BeeLogger) Critical(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Critical(format, v...) -} - -// Error Log ERROR level message. -func (bl *BeeLogger) Error(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Error(format, v...) -} - -// Warning Log WARNING level message. -func (bl *BeeLogger) Warning(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Warning(format, v...) -} - -// Notice Log NOTICE level message. -func (bl *BeeLogger) Notice(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Notice(format, v...) -} - -// Informational Log INFORMATIONAL level message. -func (bl *BeeLogger) Informational(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Informational(format, v...) -} - -// Debug Log DEBUG level message. -func (bl *BeeLogger) Debug(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Debug(format, v...) -} - -// Warn Log WARN level message. -// compatibility alias for Warning() -func (bl *BeeLogger) Warn(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Warn(format, v...) -} - -// Info Log INFO level message. -// compatibility alias for Informational() -func (bl *BeeLogger) Info(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Info(format, v...) -} - -// Trace Log TRACE level message. -// compatibility alias for Debug() -func (bl *BeeLogger) Trace(format string, v ...interface{}) { - (*logs.BeeLogger)(bl).Trace(format, v...) -} - -// Flush flush all chan data. -func (bl *BeeLogger) Flush() { - (*logs.BeeLogger)(bl).Flush() -} - -// Close close logger, flush all chan data and destroy all adapters in BeeLogger. -func (bl *BeeLogger) Close() { - (*logs.BeeLogger)(bl).Close() -} - -// Reset close all outputs, and set bl.outputs to nil -func (bl *BeeLogger) Reset() { - (*logs.BeeLogger)(bl).Reset() -} - -// GetBeeLogger returns the default BeeLogger -func GetBeeLogger() *BeeLogger { - return (*BeeLogger)(logs.GetBeeLogger()) -} - -// GetLogger returns the default BeeLogger -func GetLogger(prefixes ...string) *log.Logger { - return logs.GetLogger(prefixes...) -} - -// Reset will remove all the adapter -func Reset() { - logs.Reset() -} - -// Async set the beelogger with Async mode and hold msglen messages -func Async(msgLen ...int64) *BeeLogger { - return (*BeeLogger)(logs.Async(msgLen...)) -} - -// SetLevel sets the global log level used by the simple logger. -func SetLevel(l int) { - logs.SetLevel(l) -} - -// SetPrefix sets the prefix -func SetPrefix(s string) { - logs.SetPrefix(s) -} - -// EnableFuncCallDepth enable log funcCallDepth -func EnableFuncCallDepth(b bool) { - logs.EnableFuncCallDepth(b) -} - -// SetLogFuncCall set the CallDepth, default is 4 -func SetLogFuncCall(b bool) { - logs.SetLogFuncCall(b) -} - -// SetLogFuncCallDepth set log funcCallDepth -func SetLogFuncCallDepth(d int) { - logs.SetLogFuncCallDepth(d) -} - -// SetLogger sets a new logger. -func SetLogger(adapter string, config ...string) error { - return logs.SetLogger(adapter, config...) -} - -// Emergency logs a message at emergency level. -func Emergency(f interface{}, v ...interface{}) { - logs.Emergency(f, v...) -} - -// Alert logs a message at alert level. -func Alert(f interface{}, v ...interface{}) { - logs.Alert(f, v...) -} - -// Critical logs a message at critical level. -func Critical(f interface{}, v ...interface{}) { - logs.Critical(f, v...) -} - -// Error logs a message at error level. -func Error(f interface{}, v ...interface{}) { - logs.Error(f, v...) -} - -// Warning logs a message at warning level. -func Warning(f interface{}, v ...interface{}) { - logs.Warning(f, v...) -} - -// Warn compatibility alias for Warning() -func Warn(f interface{}, v ...interface{}) { - logs.Warn(f, v...) -} - -// Notice logs a message at notice level. -func Notice(f interface{}, v ...interface{}) { - logs.Notice(f, v...) -} - -// Informational logs a message at info level. -func Informational(f interface{}, v ...interface{}) { - logs.Informational(f, v...) -} - -// Info compatibility alias for Warning() -func Info(f interface{}, v ...interface{}) { - logs.Info(f, v...) -} - -// Debug logs a message at debug level. -func Debug(f interface{}, v ...interface{}) { - logs.Debug(f, v...) -} - -// Trace logs a message at trace level. -// compatibility alias for Warning() -func Trace(f interface{}, v ...interface{}) { - logs.Trace(f, v...) -} - -func init() { - SetLogFuncCallDepth(4) -} diff --git a/adapter/logs/log_adapter.go b/adapter/logs/log_adapter.go deleted file mode 100644 index 6affe8ff..00000000 --- a/adapter/logs/log_adapter.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package logs - -import ( - "github.com/beego/beego/v2/core/logs" -) - -type oldToNewAdapter struct { - old Logger -} - -func (o *oldToNewAdapter) Init(config string) error { - return o.old.Init(config) -} - -func (o *oldToNewAdapter) WriteMsg(lm *logs.LogMsg) error { - return o.old.WriteMsg(lm.When, lm.OldStyleFormat(), lm.Level) -} - -func (o *oldToNewAdapter) Destroy() { - o.old.Destroy() -} - -func (o *oldToNewAdapter) Flush() { - o.old.Flush() -} - -func (*oldToNewAdapter) SetFormatter(f logs.LogFormatter) { - panic("unsupported operation, you should not invoke this method") -} diff --git a/adapter/logs/logger.go b/adapter/logs/logger.go deleted file mode 100644 index 58bdfc30..00000000 --- a/adapter/logs/logger.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package logs - -import ( - "github.com/beego/beego/v2/core/logs" -) - -// ColorByStatus return color by http code -// 2xx return Green -// 3xx return White -// 4xx return Yellow -// 5xx return Red -func ColorByStatus(code int) string { - return logs.ColorByStatus(code) -} - -// ColorByMethod return color by http code -func ColorByMethod(method string) string { - return logs.ColorByMethod(method) -} - -// ResetColor return reset color -func ResetColor() string { - return logs.ResetColor() -} diff --git a/adapter/logs/logger_test.go b/adapter/logs/logger_test.go deleted file mode 100644 index 42708fa5..00000000 --- a/adapter/logs/logger_test.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package logs - -import ( - "testing" -) - -func TestBeeLoggerInfo(t *testing.T) { - log := NewLogger(1000) - log.SetLogger("file", `{"net":"tcp","addr":":7020"}`) -} diff --git a/adapter/metric/prometheus.go b/adapter/metric/prometheus.go deleted file mode 100644 index 6b276171..00000000 --- a/adapter/metric/prometheus.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2020 astaxie -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package metric - -import ( - "net/http" - "reflect" - "strconv" - "strings" - "time" - - "github.com/prometheus/client_golang/prometheus" - - "github.com/beego/beego/v2" - "github.com/beego/beego/v2/core/logs" - "github.com/beego/beego/v2/server/web" -) - -func PrometheusMiddleWare(next http.Handler) http.Handler { - summaryVec := prometheus.NewSummaryVec(prometheus.SummaryOpts{ - Name: "beego", - Subsystem: "http_request", - ConstLabels: map[string]string{ - "server": web.BConfig.ServerName, - "env": web.BConfig.RunMode, - "appname": web.BConfig.AppName, - }, - Help: "The statics info for http request", - }, []string{"pattern", "method", "status"}) - - prometheus.MustRegister(summaryVec) - - registerBuildInfo() - - return http.HandlerFunc(func(writer http.ResponseWriter, q *http.Request) { - start := time.Now() - next.ServeHTTP(writer, q) - end := time.Now() - go report(end.Sub(start), writer, q, summaryVec) - }) -} - -func registerBuildInfo() { - buildInfo := prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: "beego", - Subsystem: "build_info", - Help: "The building information", - ConstLabels: map[string]string{ - "appname": web.BConfig.AppName, - "build_version": beego.BuildVersion, - "build_revision": beego.BuildGitRevision, - "build_status": beego.BuildStatus, - "build_tag": beego.BuildTag, - "build_time": strings.Replace(beego.BuildTime, "--", " ", 1), - "go_version": beego.GoVersion, - "git_branch": beego.GitBranch, - "start_time": time.Now().Format("2006-01-02 15:04:05"), - }, - }, []string{}) - - prometheus.MustRegister(buildInfo) - buildInfo.WithLabelValues().Set(1) -} - -func report(dur time.Duration, writer http.ResponseWriter, q *http.Request, vec *prometheus.SummaryVec) { - ctrl := web.BeeApp.Handlers - ctx := ctrl.GetContext() - ctx.Reset(writer, q) - defer ctrl.GiveBackContext(ctx) - - // We cannot read the status code from q.Response.StatusCode - // since the http server does not set q.Response. So q.Response is nil - // Thus, we use reflection to read the status from writer whose concrete type is http.response - responseVal := reflect.ValueOf(writer).Elem() - field := responseVal.FieldByName("status") - status := -1 - if field.IsValid() && field.Kind() == reflect.Int { - status = int(field.Int()) - } - ptn := "UNKNOWN" - if rt, found := ctrl.FindRouter(ctx); found { - ptn = rt.GetPattern() - } else { - logs.Warn("we can not find the router info for this request, so request will be recorded as UNKNOWN: " + q.URL.String()) - } - ms := dur / time.Millisecond - vec.WithLabelValues(ptn, q.Method, strconv.Itoa(status)).Observe(float64(ms)) -} diff --git a/adapter/metric/prometheus_test.go b/adapter/metric/prometheus_test.go deleted file mode 100644 index 72212dd4..00000000 --- a/adapter/metric/prometheus_test.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 astaxie -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package metric - -import ( - "fmt" - "net/http" - "net/url" - "testing" - "time" - - "github.com/prometheus/client_golang/prometheus" - - "github.com/beego/beego/v2/adapter/context" -) - -func TestPrometheusMiddleWare(t *testing.T) { - middleware := PrometheusMiddleWare(http.HandlerFunc(func(http.ResponseWriter, *http.Request) { - fmt.Print("you are coming") - })) - writer := &context.Response{} - request := &http.Request{ - URL: &url.URL{ - Host: "localhost", - RawPath: "/a/b/c", - }, - Method: "POST", - } - vec := prometheus.NewSummaryVec(prometheus.SummaryOpts{}, []string{"pattern", "method", "status"}) - - report(time.Second, writer, request, vec) - middleware.ServeHTTP(writer, request) -} diff --git a/adapter/migration/ddl.go b/adapter/migration/ddl.go deleted file mode 100644 index 93be2d7d..00000000 --- a/adapter/migration/ddl.go +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package migration - -import ( - "github.com/beego/beego/v2/client/orm/migration" -) - -// Index struct defines the structure of Index Columns -type Index migration.Index - -// Unique struct defines a single unique key combination -type Unique migration.Unique - -// Column struct defines a single column of a table -type Column migration.Column - -// Foreign struct defines a single foreign relationship -type Foreign migration.Foreign - -// RenameColumn struct allows renaming of columns -type RenameColumn migration.RenameColumn - -// CreateTable creates the table on system -func (m *Migration) CreateTable(tablename, engine, charset string, p ...func()) { - (*migration.Migration)(m).CreateTable(tablename, engine, charset, p...) -} - -// AlterTable set the ModifyType to alter -func (m *Migration) AlterTable(tablename string) { - (*migration.Migration)(m).AlterTable(tablename) -} - -// NewCol creates a new standard column and attaches it to m struct -func (m *Migration) NewCol(name string) *Column { - return (*Column)((*migration.Migration)(m).NewCol(name)) -} - -// PriCol creates a new primary column and attaches it to m struct -func (m *Migration) PriCol(name string) *Column { - return (*Column)((*migration.Migration)(m).PriCol(name)) -} - -// UniCol creates / appends columns to specified unique key and attaches it to m struct -func (m *Migration) UniCol(uni, name string) *Column { - return (*Column)((*migration.Migration)(m).UniCol(uni, name)) -} - -// ForeignCol creates a new foreign column and returns the instance of column -func (m *Migration) ForeignCol(colname, foreigncol, foreigntable string) (foreign *Foreign) { - return (*Foreign)((*migration.Migration)(m).ForeignCol(colname, foreigncol, foreigntable)) -} - -// SetOnDelete sets the on delete of foreign -func (foreign *Foreign) SetOnDelete(del string) *Foreign { - (*migration.Foreign)(foreign).SetOnDelete(del) - return foreign -} - -// SetOnUpdate sets the on update of foreign -func (foreign *Foreign) SetOnUpdate(update string) *Foreign { - (*migration.Foreign)(foreign).SetOnUpdate(update) - return foreign -} - -// Remove marks the columns to be removed. -// it allows reverse m to create the column. -func (c *Column) Remove() { - (*migration.Column)(c).Remove() -} - -// SetAuto enables auto_increment of column (can be used once) -func (c *Column) SetAuto(inc bool) *Column { - (*migration.Column)(c).SetAuto(inc) - return c -} - -// SetNullable sets the column to be null -func (c *Column) SetNullable(null bool) *Column { - (*migration.Column)(c).SetNullable(null) - return c -} - -// SetDefault sets the default value, prepend with "DEFAULT " -func (c *Column) SetDefault(def string) *Column { - (*migration.Column)(c).SetDefault(def) - return c -} - -// SetUnsigned sets the column to be unsigned int -func (c *Column) SetUnsigned(unsign bool) *Column { - (*migration.Column)(c).SetUnsigned(unsign) - return c -} - -// SetDataType sets the dataType of the column -func (c *Column) SetDataType(dataType string) *Column { - (*migration.Column)(c).SetDataType(dataType) - return c -} - -// SetOldNullable allows reverting to previous nullable on reverse ms -func (c *RenameColumn) SetOldNullable(null bool) *RenameColumn { - (*migration.RenameColumn)(c).SetOldNullable(null) - return c -} - -// SetOldDefault allows reverting to previous default on reverse ms -func (c *RenameColumn) SetOldDefault(def string) *RenameColumn { - (*migration.RenameColumn)(c).SetOldDefault(def) - return c -} - -// SetOldUnsigned allows reverting to previous unsgined on reverse ms -func (c *RenameColumn) SetOldUnsigned(unsign bool) *RenameColumn { - (*migration.RenameColumn)(c).SetOldUnsigned(unsign) - return c -} - -// SetOldDataType allows reverting to previous datatype on reverse ms -func (c *RenameColumn) SetOldDataType(dataType string) *RenameColumn { - (*migration.RenameColumn)(c).SetOldDataType(dataType) - return c -} - -// SetPrimary adds the columns to the primary key (can only be used any number of times in only one m) -func (c *Column) SetPrimary(m *Migration) *Column { - (*migration.Column)(c).SetPrimary((*migration.Migration)(m)) - return c -} - -// AddColumnsToUnique adds the columns to Unique Struct -func (unique *Unique) AddColumnsToUnique(columns ...*Column) *Unique { - cls := toNewColumnsArray(columns) - (*migration.Unique)(unique).AddColumnsToUnique(cls...) - return unique -} - -// AddColumns adds columns to m struct -func (m *Migration) AddColumns(columns ...*Column) *Migration { - cls := toNewColumnsArray(columns) - (*migration.Migration)(m).AddColumns(cls...) - return m -} - -func toNewColumnsArray(columns []*Column) []*migration.Column { - cls := make([]*migration.Column, 0, len(columns)) - for _, c := range columns { - cls = append(cls, (*migration.Column)(c)) - } - return cls -} - -// AddPrimary adds the column to primary in m struct -func (m *Migration) AddPrimary(primary *Column) *Migration { - (*migration.Migration)(m).AddPrimary((*migration.Column)(primary)) - return m -} - -// AddUnique adds the column to unique in m struct -func (m *Migration) AddUnique(unique *Unique) *Migration { - (*migration.Migration)(m).AddUnique((*migration.Unique)(unique)) - return m -} - -// AddForeign adds the column to foreign in m struct -func (m *Migration) AddForeign(foreign *Foreign) *Migration { - (*migration.Migration)(m).AddForeign((*migration.Foreign)(foreign)) - return m -} - -// AddIndex adds the column to index in m struct -func (m *Migration) AddIndex(index *Index) *Migration { - (*migration.Migration)(m).AddIndex((*migration.Index)(index)) - return m -} - -// RenameColumn allows renaming of columns -func (m *Migration) RenameColumn(from, to string) *RenameColumn { - return (*RenameColumn)((*migration.Migration)(m).RenameColumn(from, to)) -} - -// GetSQL returns the generated sql depending on ModifyType -func (m *Migration) GetSQL() (sql string) { - return (*migration.Migration)(m).GetSQL() -} diff --git a/adapter/migration/doc.go b/adapter/migration/doc.go deleted file mode 100644 index 0c6564d4..00000000 --- a/adapter/migration/doc.go +++ /dev/null @@ -1,32 +0,0 @@ -// Package migration enables you to generate migrations back and forth. It generates both migrations. -// -// //Creates a table -// m.CreateTable("tablename","InnoDB","utf8"); -// -// //Alter a table -// m.AlterTable("tablename") -// -// Standard Column Methods -// * SetDataType -// * SetNullable -// * SetDefault -// * SetUnsigned (use only on integer types unless produces error) -// -// //Sets a primary column, multiple calls allowed, standard column methods available -// m.PriCol("id").SetAuto(true).SetNullable(false).SetDataType("INT(10)").SetUnsigned(true) -// -// //UniCol Can be used multiple times, allows standard Column methods. Use same "index" string to add to same index -// m.UniCol("index","column") -// -// //Standard Column Initialisation, can call .Remove() after NewCol("") on alter to remove -// m.NewCol("name").SetDataType("VARCHAR(255) COLLATE utf8_unicode_ci").SetNullable(false) -// m.NewCol("value").SetDataType("DOUBLE(8,2)").SetNullable(false) -// -// //Rename Columns , only use with Alter table, doesn't works with Create, prefix standard column methods with "Old" to -// //create a true reversible migration eg: SetOldDataType("DOUBLE(12,3)") -// m.RenameColumn("from","to")... -// -// //Foreign Columns, single columns are only supported, SetOnDelete & SetOnUpdate are available, call appropriately. -// //Supports standard column methods, automatic reverse. -// m.ForeignCol("local_col","foreign_col","foreign_table") -package migration diff --git a/adapter/migration/migration.go b/adapter/migration/migration.go deleted file mode 100644 index 57202232..00000000 --- a/adapter/migration/migration.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package migration is used for migration -// -// The table structure is as follow: -// -// CREATE TABLE `migrations` ( -// `id_migration` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'surrogate key', -// `name` varchar(255) DEFAULT NULL COMMENT 'migration name, unique', -// `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'date migrated or rolled back', -// `statements` longtext COMMENT 'SQL statements for this migration', -// `rollback_statements` longtext, -// `status` enum('update','rollback') DEFAULT NULL COMMENT 'update indicates it is a normal migration while rollback means this migration is rolled back', -// PRIMARY KEY (`id_migration`) -// ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -package migration - -import ( - "github.com/beego/beego/v2/client/orm/migration" -) - -// const the data format for the bee generate migration datatype -const ( - DateFormat = "20060102_150405" - DBDateFormat = "2006-01-02 15:04:05" -) - -// Migrationer is an interface for all Migration struct -type Migrationer interface { - Up() - Down() - Reset() - Exec(name, status string) error - GetCreated() int64 -} - -// Migration defines the migrations by either SQL or DDL -type Migration migration.Migration - -// Up implement in the Inheritance struct for upgrade -func (m *Migration) Up() { - (*migration.Migration)(m).Up() -} - -// Down implement in the Inheritance struct for down -func (m *Migration) Down() { - (*migration.Migration)(m).Down() -} - -// Migrate adds the SQL to the execution list -func (m *Migration) Migrate(migrationType string) { - (*migration.Migration)(m).Migrate(migrationType) -} - -// SQL add sql want to execute -func (m *Migration) SQL(sql string) { - (*migration.Migration)(m).SQL(sql) -} - -// Reset the sqls -func (m *Migration) Reset() { - (*migration.Migration)(m).Reset() -} - -// Exec execute the sql already add in the sql -func (m *Migration) Exec(name, status string) error { - return (*migration.Migration)(m).Exec(name, status) -} - -// GetCreated get the unixtime from the Created -func (m *Migration) GetCreated() int64 { - return (*migration.Migration)(m).GetCreated() -} - -// Register register the Migration in the map -func Register(name string, m Migrationer) error { - return migration.Register(name, m) -} - -// Upgrade upgrade the migration from lasttime -func Upgrade(lasttime int64) error { - return migration.Upgrade(lasttime) -} - -// Rollback rollback the migration by the name -func Rollback(name string) error { - return migration.Rollback(name) -} - -// Reset reset all migration -// run all migration's down function -func Reset() error { - return migration.Reset() -} - -// Refresh first Reset, then Upgrade -func Refresh() error { - return migration.Refresh() -} diff --git a/adapter/namespace.go b/adapter/namespace.go deleted file mode 100644 index 9c3dcbb9..00000000 --- a/adapter/namespace.go +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "net/http" - - adtContext "github.com/beego/beego/v2/adapter/context" - "github.com/beego/beego/v2/server/web" - "github.com/beego/beego/v2/server/web/context" -) - -type namespaceCond func(*adtContext.Context) bool - -// LinkNamespace used as link action -type LinkNamespace func(*Namespace) - -// Namespace is store all the info -type Namespace web.Namespace - -// NewNamespace get new Namespace -func NewNamespace(prefix string, params ...LinkNamespace) *Namespace { - nps := oldToNewLinkNs(params) - return (*Namespace)(web.NewNamespace(prefix, nps...)) -} - -func oldToNewLinkNs(params []LinkNamespace) []web.LinkNamespace { - nps := make([]web.LinkNamespace, 0, len(params)) - for i := 0; i < len(params); i++ { - p := params[i] - nps = append(nps, func(namespace *web.Namespace) { - p((*Namespace)(namespace)) - }) - } - return nps -} - -// Cond set condition function -// if cond return true can run this namespace, else can't -// usage: -// ns.Cond(func (ctx *context.Context) bool{ -// if ctx.Input.Domain() == "api.beego.vip" { -// return true -// } -// return false -// }) -// Cond as the first filter -func (n *Namespace) Cond(cond namespaceCond) *Namespace { - (*web.Namespace)(n).Cond(func(context *context.Context) bool { - return cond((*adtContext.Context)(context)) - }) - return n -} - -// Filter add filter in the Namespace -// action has before & after -// FilterFunc -// usage: -// Filter("before", func (ctx *context.Context){ -// _, ok := ctx.Input.Session("uid").(int) -// if !ok && ctx.Request.RequestURI != "/login" { -// ctx.Redirect(302, "/login") -// } -// }) -func (n *Namespace) Filter(action string, filter ...FilterFunc) *Namespace { - nfs := oldToNewFilter(filter) - (*web.Namespace)(n).Filter(action, nfs...) - return n -} - -func oldToNewFilter(filter []FilterFunc) []web.FilterFunc { - nfs := make([]web.FilterFunc, 0, len(filter)) - for i := 0; i < len(filter); i++ { - f := filter[i] - nfs = append(nfs, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - } - return nfs -} - -// Router same as beego.Rourer -// refer: https://godoc.org/github.com/beego/beego/v2#Router -func (n *Namespace) Router(rootpath string, c ControllerInterface, mappingMethods ...string) *Namespace { - (*web.Namespace)(n).Router(rootpath, c, mappingMethods...) - return n -} - -// AutoRouter same as beego.AutoRouter -// refer: https://godoc.org/github.com/beego/beego/v2#AutoRouter -func (n *Namespace) AutoRouter(c ControllerInterface) *Namespace { - (*web.Namespace)(n).AutoRouter(c) - return n -} - -// AutoPrefix same as beego.AutoPrefix -// refer: https://godoc.org/github.com/beego/beego/v2#AutoPrefix -func (n *Namespace) AutoPrefix(prefix string, c ControllerInterface) *Namespace { - (*web.Namespace)(n).AutoPrefix(prefix, c) - return n -} - -// Get same as beego.Get -// refer: https://godoc.org/github.com/beego/beego/v2#Get -func (n *Namespace) Get(rootpath string, f FilterFunc) *Namespace { - (*web.Namespace)(n).Get(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return n -} - -// Post same as beego.Post -// refer: https://godoc.org/github.com/beego/beego/v2#Post -func (n *Namespace) Post(rootpath string, f FilterFunc) *Namespace { - (*web.Namespace)(n).Post(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return n -} - -// Delete same as beego.Delete -// refer: https://godoc.org/github.com/beego/beego/v2#Delete -func (n *Namespace) Delete(rootpath string, f FilterFunc) *Namespace { - (*web.Namespace)(n).Delete(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return n -} - -// Put same as beego.Put -// refer: https://godoc.org/github.com/beego/beego/v2#Put -func (n *Namespace) Put(rootpath string, f FilterFunc) *Namespace { - (*web.Namespace)(n).Put(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return n -} - -// Head same as beego.Head -// refer: https://godoc.org/github.com/beego/beego/v2#Head -func (n *Namespace) Head(rootpath string, f FilterFunc) *Namespace { - (*web.Namespace)(n).Head(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return n -} - -// Options same as beego.Options -// refer: https://godoc.org/github.com/beego/beego/v2#Options -func (n *Namespace) Options(rootpath string, f FilterFunc) *Namespace { - (*web.Namespace)(n).Options(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return n -} - -// Patch same as beego.Patch -// refer: https://godoc.org/github.com/beego/beego/v2#Patch -func (n *Namespace) Patch(rootpath string, f FilterFunc) *Namespace { - (*web.Namespace)(n).Patch(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return n -} - -// Any same as beego.Any -// refer: https://godoc.org/github.com/beego/beego/v2#Any -func (n *Namespace) Any(rootpath string, f FilterFunc) *Namespace { - (*web.Namespace)(n).Any(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return n -} - -// Handler same as beego.Handler -// refer: https://godoc.org/github.com/beego/beego/v2#Handler -func (n *Namespace) Handler(rootpath string, h http.Handler) *Namespace { - (*web.Namespace)(n).Handler(rootpath, h) - return n -} - -// Include add include class -// refer: https://godoc.org/github.com/beego/beego/v2#Include -func (n *Namespace) Include(cList ...ControllerInterface) *Namespace { - nL := oldToNewCtrlIntfs(cList) - (*web.Namespace)(n).Include(nL...) - return n -} - -// Namespace add nest Namespace -// usage: -// ns := beego.NewNamespace(“/v1”). -// Namespace( -// beego.NewNamespace("/shop"). -// Get("/:id", func(ctx *context.Context) { -// ctx.Output.Body([]byte("shopinfo")) -// }), -// beego.NewNamespace("/order"). -// Get("/:id", func(ctx *context.Context) { -// ctx.Output.Body([]byte("orderinfo")) -// }), -// beego.NewNamespace("/crm"). -// Get("/:id", func(ctx *context.Context) { -// ctx.Output.Body([]byte("crminfo")) -// }), -// ) -func (n *Namespace) Namespace(ns ...*Namespace) *Namespace { - nns := oldToNewNs(ns) - (*web.Namespace)(n).Namespace(nns...) - return n -} - -func oldToNewNs(ns []*Namespace) []*web.Namespace { - nns := make([]*web.Namespace, 0, len(ns)) - for _, n := range ns { - nns = append(nns, (*web.Namespace)(n)) - } - return nns -} - -// AddNamespace register Namespace into beego.Handler -// support multi Namespace -func AddNamespace(nl ...*Namespace) { - nnl := oldToNewNs(nl) - web.AddNamespace(nnl...) -} - -// NSCond is Namespace Condition -func NSCond(cond namespaceCond) LinkNamespace { - wc := web.NSCond(func(b *context.Context) bool { - return cond((*adtContext.Context)(b)) - }) - return func(namespace *Namespace) { - wc((*web.Namespace)(namespace)) - } -} - -// NSBefore Namespace BeforeRouter filter -func NSBefore(filterList ...FilterFunc) LinkNamespace { - nfs := oldToNewFilter(filterList) - wf := web.NSBefore(nfs...) - return func(namespace *Namespace) { - wf((*web.Namespace)(namespace)) - } -} - -// NSAfter add Namespace FinishRouter filter -func NSAfter(filterList ...FilterFunc) LinkNamespace { - nfs := oldToNewFilter(filterList) - wf := web.NSAfter(nfs...) - return func(namespace *Namespace) { - wf((*web.Namespace)(namespace)) - } -} - -// NSInclude Namespace Include ControllerInterface -func NSInclude(cList ...ControllerInterface) LinkNamespace { - nfs := oldToNewCtrlIntfs(cList) - wi := web.NSInclude(nfs...) - return func(namespace *Namespace) { - wi((*web.Namespace)(namespace)) - } -} - -// NSRouter call Namespace Router -func NSRouter(rootpath string, c ControllerInterface, mappingMethods ...string) LinkNamespace { - wn := web.NSRouter(rootpath, c, mappingMethods...) - return func(namespace *Namespace) { - wn((*web.Namespace)(namespace)) - } -} - -// NSGet call Namespace Get -func NSGet(rootpath string, f FilterFunc) LinkNamespace { - ln := web.NSGet(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return func(ns *Namespace) { - ln((*web.Namespace)(ns)) - } -} - -// NSPost call Namespace Post -func NSPost(rootpath string, f FilterFunc) LinkNamespace { - wp := web.NSPost(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return func(ns *Namespace) { - wp((*web.Namespace)(ns)) - } -} - -// NSHead call Namespace Head -func NSHead(rootpath string, f FilterFunc) LinkNamespace { - wb := web.NSHead(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return func(ns *Namespace) { - wb((*web.Namespace)(ns)) - } -} - -// NSPut call Namespace Put -func NSPut(rootpath string, f FilterFunc) LinkNamespace { - wn := web.NSPut(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return func(ns *Namespace) { - wn((*web.Namespace)(ns)) - } -} - -// NSDelete call Namespace Delete -func NSDelete(rootpath string, f FilterFunc) LinkNamespace { - wn := web.NSDelete(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return func(ns *Namespace) { - wn((*web.Namespace)(ns)) - } -} - -// NSAny call Namespace Any -func NSAny(rootpath string, f FilterFunc) LinkNamespace { - wn := web.NSAny(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return func(ns *Namespace) { - wn((*web.Namespace)(ns)) - } -} - -// NSOptions call Namespace Options -func NSOptions(rootpath string, f FilterFunc) LinkNamespace { - wo := web.NSOptions(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return func(ns *Namespace) { - wo((*web.Namespace)(ns)) - } -} - -// NSPatch call Namespace Patch -func NSPatch(rootpath string, f FilterFunc) LinkNamespace { - wn := web.NSPatch(rootpath, func(ctx *context.Context) { - f((*adtContext.Context)(ctx)) - }) - return func(ns *Namespace) { - wn((*web.Namespace)(ns)) - } -} - -// NSAutoRouter call Namespace AutoRouter -func NSAutoRouter(c ControllerInterface) LinkNamespace { - wn := web.NSAutoRouter(c) - return func(ns *Namespace) { - wn((*web.Namespace)(ns)) - } -} - -// NSAutoPrefix call Namespace AutoPrefix -func NSAutoPrefix(prefix string, c ControllerInterface) LinkNamespace { - wn := web.NSAutoPrefix(prefix, c) - return func(ns *Namespace) { - wn((*web.Namespace)(ns)) - } -} - -// NSNamespace add sub Namespace -func NSNamespace(prefix string, params ...LinkNamespace) LinkNamespace { - nps := oldToNewLinkNs(params) - wn := web.NSNamespace(prefix, nps...) - return func(ns *Namespace) { - wn((*web.Namespace)(ns)) - } -} - -// NSHandler add handler -func NSHandler(rootpath string, h http.Handler) LinkNamespace { - wn := web.NSHandler(rootpath, h) - return func(ns *Namespace) { - wn((*web.Namespace)(ns)) - } -} diff --git a/adapter/orm/cmd.go b/adapter/orm/cmd.go deleted file mode 100644 index d8399c90..00000000 --- a/adapter/orm/cmd.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "github.com/beego/beego/v2/client/orm" -) - -// RunCommand listen for orm command and then run it if command arguments passed. -func RunCommand() { - orm.RunCommand() -} - -func RunSyncdb(name string, force bool, verbose bool) error { - return orm.RunSyncdb(name, force, verbose) -} diff --git a/adapter/orm/db.go b/adapter/orm/db.go deleted file mode 100644 index c1d1fe92..00000000 --- a/adapter/orm/db.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "github.com/beego/beego/v2/client/orm" -) - -// ErrMissPK missing pk error -var ErrMissPK = orm.ErrMissPK diff --git a/adapter/orm/db_alias.go b/adapter/orm/db_alias.go deleted file mode 100644 index a196ca23..00000000 --- a/adapter/orm/db_alias.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "context" - "database/sql" - "time" - - "github.com/beego/beego/v2/client/orm" -) - -// DriverType database driver constant int. -type DriverType orm.DriverType - -// Enum the Database driver -const ( - DRMySQL = DriverType(orm.DRMySQL) - DRSqlite = DriverType(orm.DRSqlite) // sqlite - DROracle = DriverType(orm.DROracle) // oracle - DRPostgres = DriverType(orm.DRPostgres) // pgsql - DRTiDB = DriverType(orm.DRTiDB) // TiDB -) - -type DB orm.DB - -func (d *DB) Begin() (*sql.Tx, error) { - return (*orm.DB)(d).Begin() -} - -func (d *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error) { - return (*orm.DB)(d).BeginTx(ctx, opts) -} - -func (d *DB) Prepare(query string) (*sql.Stmt, error) { - return (*orm.DB)(d).Prepare(query) -} - -func (d *DB) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) { - return (*orm.DB)(d).PrepareContext(ctx, query) -} - -func (d *DB) Exec(query string, args ...interface{}) (sql.Result, error) { - return (*orm.DB)(d).Exec(query, args...) -} - -func (d *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) { - return (*orm.DB)(d).ExecContext(ctx, query, args...) -} - -func (d *DB) Query(query string, args ...interface{}) (*sql.Rows, error) { - return (*orm.DB)(d).Query(query, args...) -} - -func (d *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) { - return (*orm.DB)(d).QueryContext(ctx, query, args...) -} - -func (d *DB) QueryRow(query string, args ...interface{}) *sql.Row { - return (*orm.DB)(d).QueryRow(query, args...) -} - -func (d *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row { - return (*orm.DB)(d).QueryRowContext(ctx, query, args...) -} - -// AddAliasWthDB add a aliasName for the drivename -func AddAliasWthDB(aliasName, driverName string, db *sql.DB) error { - return orm.AddAliasWthDB(aliasName, driverName, db) -} - -// RegisterDataBase Setting the database connect params. Use the database driver self dataSource args. -func RegisterDataBase(aliasName, driverName, dataSource string, params ...int) error { - opts := make([]orm.DBOption, 0, 2) - if len(params) > 0 { - opts = append(opts, orm.MaxIdleConnections(params[0])) - } - - if len(params) > 1 { - opts = append(opts, orm.MaxOpenConnections(params[1])) - } - return orm.RegisterDataBase(aliasName, driverName, dataSource, opts...) -} - -// RegisterDriver Register a database driver use specify driver name, this can be definition the driver is which database type. -func RegisterDriver(driverName string, typ DriverType) error { - return orm.RegisterDriver(driverName, orm.DriverType(typ)) -} - -// SetDataBaseTZ Change the database default used timezone -func SetDataBaseTZ(aliasName string, tz *time.Location) error { - return orm.SetDataBaseTZ(aliasName, tz) -} - -// SetMaxIdleConns Change the max idle conns for *sql.DB, use specify database alias name -func SetMaxIdleConns(aliasName string, maxIdleConns int) { - orm.SetMaxIdleConns(aliasName, maxIdleConns) -} - -// SetMaxOpenConns Change the max open conns for *sql.DB, use specify database alias name -func SetMaxOpenConns(aliasName string, maxOpenConns int) { - orm.SetMaxOpenConns(aliasName, maxOpenConns) -} - -// GetDB Get *sql.DB from registered database by db alias name. -// Use "default" as alias name if you not set. -func GetDB(aliasNames ...string) (*sql.DB, error) { - return orm.GetDB(aliasNames...) -} diff --git a/adapter/orm/models.go b/adapter/orm/models.go deleted file mode 100644 index ee6b9194..00000000 --- a/adapter/orm/models.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "github.com/beego/beego/v2/client/orm" -) - -// ResetModelCache Clean model cache. Then you can re-RegisterModel. -// Common use this api for test case. -func ResetModelCache() { - orm.ResetModelCache() -} diff --git a/adapter/orm/models_boot.go b/adapter/orm/models_boot.go deleted file mode 100644 index 678b86e6..00000000 --- a/adapter/orm/models_boot.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "github.com/beego/beego/v2/client/orm" -) - -// RegisterModel register models -func RegisterModel(models ...interface{}) { - orm.RegisterModel(models...) -} - -// RegisterModelWithPrefix register models with a prefix -func RegisterModelWithPrefix(prefix string, models ...interface{}) { - orm.RegisterModelWithPrefix(prefix, models...) -} - -// RegisterModelWithSuffix register models with a suffix -func RegisterModelWithSuffix(suffix string, models ...interface{}) { - orm.RegisterModelWithSuffix(suffix, models...) -} - -// BootStrap bootstrap models. -// make all model parsed and can not add more models -func BootStrap() { - orm.BootStrap() -} diff --git a/adapter/orm/models_boot_test.go b/adapter/orm/models_boot_test.go deleted file mode 100644 index 5471885b..00000000 --- a/adapter/orm/models_boot_test.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2020 beego -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "testing" -) - -type User struct { - Id int -} - -type Seller struct { - Id int -} - -func TestRegisterModelWithPrefix(t *testing.T) { - RegisterModelWithPrefix("test", &User{}, &Seller{}) -} diff --git a/adapter/orm/orm.go b/adapter/orm/orm.go deleted file mode 100644 index 2b2b29e0..00000000 --- a/adapter/orm/orm.go +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build go1.8 -// +build go1.8 - -// Package orm provide ORM for MySQL/PostgreSQL/sqlite -// Simple Usage -// -// package main -// -// import ( -// "fmt" -// "github.com/beego/beego/v2/client/orm" -// _ "github.com/go-sql-driver/mysql" // import your used driver -// ) -// -// // Model Struct -// type User struct { -// Id int `orm:"auto"` -// Name string `orm:"size(100)"` -// } -// -// func init() { -// orm.RegisterDataBase("default", "mysql", "root:root@/my_db?charset=utf8", 30) -// } -// -// func main() { -// o := orm.NewOrm() -// user := User{Name: "slene"} -// // insert -// id, err := o.Insert(&user) -// // update -// user.Name = "astaxie" -// num, err := o.Update(&user) -// // read one -// u := User{Id: user.Id} -// err = o.Read(&u) -// // delete -// num, err = o.Delete(&u) -// } -// -package orm - -import ( - "context" - "database/sql" - "errors" - - "github.com/beego/beego/v2/client/orm" - "github.com/beego/beego/v2/client/orm/hints" - "github.com/beego/beego/v2/core/utils" -) - -// DebugQueries define the debug -const ( - DebugQueries = iota -) - -// Define common vars -var ( - Debug = orm.Debug - DebugLog = orm.DebugLog - DefaultRowsLimit = orm.DefaultRowsLimit - DefaultRelsDepth = orm.DefaultRelsDepth - DefaultTimeLoc = orm.DefaultTimeLoc - ErrTxHasBegan = errors.New(" transaction already begin") - ErrTxDone = errors.New(" transaction not begin") - ErrMultiRows = errors.New(" return multi rows") - ErrNoRows = errors.New(" no row found") - ErrStmtClosed = errors.New(" stmt already closed") - ErrArgs = errors.New(" args error may be empty") - ErrNotImplement = errors.New("have not implement") -) - -type ormer struct { - delegate orm.Ormer - txDelegate orm.TxOrmer - isTx bool -} - -var _ Ormer = new(ormer) - -// Read read data to model -func (o *ormer) Read(md interface{}, cols ...string) error { - if o.isTx { - return o.txDelegate.Read(md, cols...) - } - return o.delegate.Read(md, cols...) -} - -// ReadForUpdate read data to model, like Read(), but use "SELECT FOR UPDATE" form -func (o *ormer) ReadForUpdate(md interface{}, cols ...string) error { - if o.isTx { - return o.txDelegate.ReadForUpdate(md, cols...) - } - return o.delegate.ReadForUpdate(md, cols...) -} - -// ReadOrCreate Try to read a row from the database, or insert one if it doesn't exist -func (o *ormer) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) { - if o.isTx { - return o.txDelegate.ReadOrCreate(md, col1, cols...) - } - return o.delegate.ReadOrCreate(md, col1, cols...) -} - -// Insert will insert model data to database -func (o *ormer) Insert(md interface{}) (int64, error) { - if o.isTx { - return o.txDelegate.Insert(md) - } - return o.delegate.Insert(md) -} - -// InsertMulti will insert some models to database -func (o *ormer) InsertMulti(bulk int, mds interface{}) (int64, error) { - if o.isTx { - return o.txDelegate.InsertMulti(bulk, mds) - } - return o.delegate.InsertMulti(bulk, mds) -} - -// InsertOrUpdate data to database -func (o *ormer) InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error) { - if o.isTx { - return o.txDelegate.InsertOrUpdate(md, colConflitAndArgs...) - } - return o.delegate.InsertOrUpdate(md, colConflitAndArgs...) -} - -// Update will update model to database. -// cols set the columns those want to update. -func (o *ormer) Update(md interface{}, cols ...string) (int64, error) { - if o.isTx { - return o.txDelegate.Update(md, cols...) - } - return o.delegate.Update(md, cols...) -} - -// Delete delete model in database -// cols shows the delete conditions values read from. default is pk -func (o *ormer) Delete(md interface{}, cols ...string) (int64, error) { - if o.isTx { - return o.txDelegate.Delete(md, cols...) - } - return o.delegate.Delete(md, cols...) -} - -// QueryM2M create a models to models queryer -func (o *ormer) QueryM2M(md interface{}, name string) QueryM2Mer { - if o.isTx { - return o.txDelegate.QueryM2M(md, name) - } - return o.delegate.QueryM2M(md, name) -} - -// LoadRelated load related models to md model. -// args are limit, offset int and order string. -// -// example: -// orm.LoadRelated(post,"Tags") -// for _,tag := range post.Tags{...} -// -// make sure the relation is defined in model struct tags. -func (o *ormer) LoadRelated(md interface{}, name string, args ...interface{}) (int64, error) { - kvs := make([]utils.KV, 0, 4) - for i, arg := range args { - switch i { - case 0: - if v, ok := arg.(bool); ok { - if v { - kvs = append(kvs, hints.DefaultRelDepth()) - } - } else if v, ok := arg.(int); ok { - kvs = append(kvs, hints.RelDepth(v)) - } - case 1: - kvs = append(kvs, hints.Limit(orm.ToInt64(arg))) - case 2: - kvs = append(kvs, hints.Offset(orm.ToInt64(arg))) - case 3: - kvs = append(kvs, hints.Offset(orm.ToInt64(arg))) - } - } - if o.isTx { - return o.txDelegate.LoadRelated(md, name, kvs...) - } - return o.delegate.LoadRelated(md, name, kvs...) -} - -// QueryTable return a QuerySeter for table operations. -// table name can be string or struct. -// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)), -func (o *ormer) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { - if o.isTx { - return o.txDelegate.QueryTable(ptrStructOrTableName) - } - return o.delegate.QueryTable(ptrStructOrTableName) -} - -// Using switch to another registered database driver by given name. -func (o *ormer) Using(name string) error { - if o.isTx { - return ErrTxHasBegan - } - o.delegate = orm.NewOrmUsingDB(name) - return nil -} - -// Begin will begin transaction -func (o *ormer) Begin() error { - if o.isTx { - return ErrTxHasBegan - } - return o.BeginTx(context.Background(), nil) -} - -func (o *ormer) BeginTx(ctx context.Context, opts *sql.TxOptions) error { - if o.isTx { - return ErrTxHasBegan - } - txOrmer, err := o.delegate.BeginWithCtxAndOpts(ctx, opts) - if err != nil { - return err - } - o.txDelegate = txOrmer - o.isTx = true - return nil -} - -// Commit will commit transaction -func (o *ormer) Commit() error { - if !o.isTx { - return ErrTxDone - } - err := o.txDelegate.Commit() - if err == nil { - o.isTx = false - o.txDelegate = nil - } else if err == sql.ErrTxDone { - return ErrTxDone - } - return err -} - -// Rollback will rollback transaction -func (o *ormer) Rollback() error { - if !o.isTx { - return ErrTxDone - } - err := o.txDelegate.Rollback() - if err == nil { - o.isTx = false - o.txDelegate = nil - } else if err == sql.ErrTxDone { - return ErrTxDone - } - return err -} - -// Raw return a raw query seter for raw sql string. -func (o *ormer) Raw(query string, args ...interface{}) RawSeter { - if o.isTx { - return o.txDelegate.Raw(query, args...) - } - return o.delegate.Raw(query, args...) -} - -// Driver return current using database Driver -func (o *ormer) Driver() Driver { - if o.isTx { - return o.txDelegate.Driver() - } - return o.delegate.Driver() -} - -// DBStats return sql.DBStats for current database -func (o *ormer) DBStats() *sql.DBStats { - if o.isTx { - return o.txDelegate.DBStats() - } - return o.delegate.DBStats() -} - -// NewOrm create new orm -func NewOrm() Ormer { - o := orm.NewOrm() - return &ormer{ - delegate: o, - } -} - -// NewOrmWithDB create a new ormer object with specify *sql.DB for query -func NewOrmWithDB(driverName, aliasName string, db *sql.DB) (Ormer, error) { - o, err := orm.NewOrmWithDB(driverName, aliasName, db) - if err != nil { - return nil, err - } - return &ormer{ - delegate: o, - }, nil -} diff --git a/adapter/orm/orm_conds.go b/adapter/orm/orm_conds.go deleted file mode 100644 index 4a713fcd..00000000 --- a/adapter/orm/orm_conds.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "github.com/beego/beego/v2/client/orm" -) - -// ExprSep define the expression separation -const ( - ExprSep = "__" -) - -// Condition struct. -// work for WHERE conditions. -type Condition orm.Condition - -// NewCondition return new condition struct -func NewCondition() *Condition { - return (*Condition)(orm.NewCondition()) -} - -// Raw add raw sql to condition -func (c Condition) Raw(expr string, sql string) *Condition { - return (*Condition)((orm.Condition)(c).Raw(expr, sql)) -} - -// And add expression to condition -func (c Condition) And(expr string, args ...interface{}) *Condition { - return (*Condition)((orm.Condition)(c).And(expr, args...)) -} - -// AndNot add NOT expression to condition -func (c Condition) AndNot(expr string, args ...interface{}) *Condition { - return (*Condition)((orm.Condition)(c).AndNot(expr, args...)) -} - -// AndCond combine a condition to current condition -func (c *Condition) AndCond(cond *Condition) *Condition { - return (*Condition)((*orm.Condition)(c).AndCond((*orm.Condition)(cond))) -} - -// AndNotCond combine an AND NOT condition to current condition -func (c *Condition) AndNotCond(cond *Condition) *Condition { - return (*Condition)((*orm.Condition)(c).AndNotCond((*orm.Condition)(cond))) -} - -// Or add OR expression to condition -func (c Condition) Or(expr string, args ...interface{}) *Condition { - return (*Condition)((orm.Condition)(c).Or(expr, args...)) -} - -// OrNot add OR NOT expression to condition -func (c Condition) OrNot(expr string, args ...interface{}) *Condition { - return (*Condition)((orm.Condition)(c).OrNot(expr, args...)) -} - -// OrCond combine an OR condition to current condition -func (c *Condition) OrCond(cond *Condition) *Condition { - return (*Condition)((*orm.Condition)(c).OrCond((*orm.Condition)(cond))) -} - -// OrNotCond combine an OR NOT condition to current condition -func (c *Condition) OrNotCond(cond *Condition) *Condition { - return (*Condition)((*orm.Condition)(c).OrNotCond((*orm.Condition)(cond))) -} - -// IsEmpty check the condition arguments are empty or not. -func (c *Condition) IsEmpty() bool { - return (*orm.Condition)(c).IsEmpty() -} diff --git a/adapter/orm/orm_queryset.go b/adapter/orm/orm_queryset.go deleted file mode 100644 index b1f4c165..00000000 --- a/adapter/orm/orm_queryset.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "github.com/beego/beego/v2/client/orm" -) - -// define Col operations -const ( - ColAdd = orm.ColAdd - ColMinus = orm.ColMinus - ColMultiply = orm.ColMultiply - ColExcept = orm.ColExcept - ColBitAnd = orm.ColBitAnd - ColBitRShift = orm.ColBitRShift - ColBitLShift = orm.ColBitLShift - ColBitXOR = orm.ColBitXOR - ColBitOr = orm.ColBitOr -) diff --git a/adapter/orm/qb.go b/adapter/orm/qb.go deleted file mode 100644 index 57c8d62a..00000000 --- a/adapter/orm/qb.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "github.com/beego/beego/v2/client/orm" -) - -// QueryBuilder is the Query builder interface -type QueryBuilder orm.QueryBuilder - -// NewQueryBuilder return the QueryBuilder -func NewQueryBuilder(driver string) (qb QueryBuilder, err error) { - return orm.NewQueryBuilder(driver) -} diff --git a/adapter/orm/qb_mysql.go b/adapter/orm/qb_mysql.go deleted file mode 100644 index 10b38ea9..00000000 --- a/adapter/orm/qb_mysql.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "github.com/beego/beego/v2/client/orm" -) - -// CommaSpace is the separation -const CommaSpace = orm.CommaSpace - -// MySQLQueryBuilder is the SQL build -type MySQLQueryBuilder orm.MySQLQueryBuilder - -// Select will join the fields -func (qb *MySQLQueryBuilder) Select(fields ...string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Select(fields...) -} - -// ForUpdate add the FOR UPDATE clause -func (qb *MySQLQueryBuilder) ForUpdate() QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).ForUpdate() -} - -// From join the tables -func (qb *MySQLQueryBuilder) From(tables ...string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).From(tables...) -} - -// InnerJoin INNER JOIN the table -func (qb *MySQLQueryBuilder) InnerJoin(table string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).InnerJoin(table) -} - -// LeftJoin LEFT JOIN the table -func (qb *MySQLQueryBuilder) LeftJoin(table string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).LeftJoin(table) -} - -// RightJoin RIGHT JOIN the table -func (qb *MySQLQueryBuilder) RightJoin(table string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).RightJoin(table) -} - -// On join with on cond -func (qb *MySQLQueryBuilder) On(cond string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).On(cond) -} - -// Where join the Where cond -func (qb *MySQLQueryBuilder) Where(cond string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Where(cond) -} - -// And join the and cond -func (qb *MySQLQueryBuilder) And(cond string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).And(cond) -} - -// Or join the or cond -func (qb *MySQLQueryBuilder) Or(cond string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Or(cond) -} - -// In join the IN (vals) -func (qb *MySQLQueryBuilder) In(vals ...string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).In(vals...) -} - -// OrderBy join the Order by fields -func (qb *MySQLQueryBuilder) OrderBy(fields ...string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).OrderBy(fields...) -} - -// Asc join the asc -func (qb *MySQLQueryBuilder) Asc() QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Asc() -} - -// Desc join the desc -func (qb *MySQLQueryBuilder) Desc() QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Desc() -} - -// Limit join the limit num -func (qb *MySQLQueryBuilder) Limit(limit int) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Limit(limit) -} - -// Offset join the offset num -func (qb *MySQLQueryBuilder) Offset(offset int) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Offset(offset) -} - -// GroupBy join the Group by fields -func (qb *MySQLQueryBuilder) GroupBy(fields ...string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).GroupBy(fields...) -} - -// Having join the Having cond -func (qb *MySQLQueryBuilder) Having(cond string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Having(cond) -} - -// Update join the update table -func (qb *MySQLQueryBuilder) Update(tables ...string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Update(tables...) -} - -// Set join the set kv -func (qb *MySQLQueryBuilder) Set(kv ...string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Set(kv...) -} - -// Delete join the Delete tables -func (qb *MySQLQueryBuilder) Delete(tables ...string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Delete(tables...) -} - -// InsertInto join the insert SQL -func (qb *MySQLQueryBuilder) InsertInto(table string, fields ...string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).InsertInto(table, fields...) -} - -// Values join the Values(vals) -func (qb *MySQLQueryBuilder) Values(vals ...string) QueryBuilder { - return (*orm.MySQLQueryBuilder)(qb).Values(vals...) -} - -// Subquery join the sub as alias -func (qb *MySQLQueryBuilder) Subquery(sub string, alias string) string { - return (*orm.MySQLQueryBuilder)(qb).Subquery(sub, alias) -} - -// String join all Tokens -func (qb *MySQLQueryBuilder) String() string { - return (*orm.MySQLQueryBuilder)(qb).String() -} diff --git a/adapter/orm/qb_tidb.go b/adapter/orm/qb_tidb.go deleted file mode 100644 index d3c94e0f..00000000 --- a/adapter/orm/qb_tidb.go +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2015 TiDB Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "github.com/beego/beego/v2/client/orm" -) - -// TiDBQueryBuilder is the SQL build -type TiDBQueryBuilder orm.TiDBQueryBuilder - -// Select will join the fields -func (qb *TiDBQueryBuilder) Select(fields ...string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Select(fields...) -} - -// ForUpdate add the FOR UPDATE clause -func (qb *TiDBQueryBuilder) ForUpdate() QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).ForUpdate() -} - -// From join the tables -func (qb *TiDBQueryBuilder) From(tables ...string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).From(tables...) -} - -// InnerJoin INNER JOIN the table -func (qb *TiDBQueryBuilder) InnerJoin(table string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).InnerJoin(table) -} - -// LeftJoin LEFT JOIN the table -func (qb *TiDBQueryBuilder) LeftJoin(table string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).LeftJoin(table) -} - -// RightJoin RIGHT JOIN the table -func (qb *TiDBQueryBuilder) RightJoin(table string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).RightJoin(table) -} - -// On join with on cond -func (qb *TiDBQueryBuilder) On(cond string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).On(cond) -} - -// Where join the Where cond -func (qb *TiDBQueryBuilder) Where(cond string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Where(cond) -} - -// And join the and cond -func (qb *TiDBQueryBuilder) And(cond string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).And(cond) -} - -// Or join the or cond -func (qb *TiDBQueryBuilder) Or(cond string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Or(cond) -} - -// In join the IN (vals) -func (qb *TiDBQueryBuilder) In(vals ...string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).In(vals...) -} - -// OrderBy join the Order by fields -func (qb *TiDBQueryBuilder) OrderBy(fields ...string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).OrderBy(fields...) -} - -// Asc join the asc -func (qb *TiDBQueryBuilder) Asc() QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Asc() -} - -// Desc join the desc -func (qb *TiDBQueryBuilder) Desc() QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Desc() -} - -// Limit join the limit num -func (qb *TiDBQueryBuilder) Limit(limit int) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Limit(limit) -} - -// Offset join the offset num -func (qb *TiDBQueryBuilder) Offset(offset int) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Offset(offset) -} - -// GroupBy join the Group by fields -func (qb *TiDBQueryBuilder) GroupBy(fields ...string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).GroupBy(fields...) -} - -// Having join the Having cond -func (qb *TiDBQueryBuilder) Having(cond string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Having(cond) -} - -// Update join the update table -func (qb *TiDBQueryBuilder) Update(tables ...string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Update(tables...) -} - -// Set join the set kv -func (qb *TiDBQueryBuilder) Set(kv ...string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Set(kv...) -} - -// Delete join the Delete tables -func (qb *TiDBQueryBuilder) Delete(tables ...string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Delete(tables...) -} - -// InsertInto join the insert SQL -func (qb *TiDBQueryBuilder) InsertInto(table string, fields ...string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).InsertInto(table, fields...) -} - -// Values join the Values(vals) -func (qb *TiDBQueryBuilder) Values(vals ...string) QueryBuilder { - return (*orm.TiDBQueryBuilder)(qb).Values(vals...) -} - -// Subquery join the sub as alias -func (qb *TiDBQueryBuilder) Subquery(sub string, alias string) string { - return (*orm.TiDBQueryBuilder)(qb).Subquery(sub, alias) -} - -// String join all Tokens -func (qb *TiDBQueryBuilder) String() string { - return (*orm.TiDBQueryBuilder)(qb).String() -} diff --git a/adapter/orm/types.go b/adapter/orm/types.go deleted file mode 100644 index ecc4d6f4..00000000 --- a/adapter/orm/types.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "context" - "database/sql" - - "github.com/beego/beego/v2/client/orm" -) - -// Params stores the Params -type Params orm.Params - -// ParamsList stores paramslist -type ParamsList orm.ParamsList - -// Driver define database driver -type Driver orm.Driver - -// Fielder define field info -type Fielder orm.Fielder - -// Ormer define the orm interface -type Ormer interface { - // Read read data to model - // for example: - // this will find User by Id field - // u = &User{Id: user.Id} - // err = Ormer.Read(u) - // this will find User by UserName field - // u = &User{UserName: "astaxie", Password: "pass"} - // err = Ormer.Read(u, "UserName") - Read(md interface{}, cols ...string) error - // ReadForUpdate Like Read(), but with "FOR UPDATE" clause, useful in transaction. - // Some databases are not support this feature. - ReadForUpdate(md interface{}, cols ...string) error - // ReadOrCreate Try to read a row from the database, or insert one if it doesn't exist - ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) - // Insert will insert model data to database - // for example: - // user := new(User) - // id, err = Ormer.Insert(user) - // user must be a pointer and Insert will set user's pk field - Insert(interface{}) (int64, error) - // InsertOrUpdate(model,"colu=colu+value") or mysql:InsertOrUpdate(model) - // if colu type is integer : can use(+-*/), string : convert(colu,"value") - // postgres: InsertOrUpdate(model,"conflictColumnName") or InsertOrUpdate(model,"conflictColumnName","colu=colu+value") - // if colu type is integer : can use(+-*/), string : colu || "value" - InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error) - // InsertMulti insert some models to database - InsertMulti(bulk int, mds interface{}) (int64, error) - // Update update model to database. - // cols set the columns those want to update. - // find model by Id(pk) field and update columns specified by fields, if cols is null then update all columns - // for example: - // user := User{Id: 2} - // user.Langs = append(user.Langs, "zh-CN", "en-US") - // user.Extra.Name = "beego" - // user.Extra.Data = "orm" - // num, err = Ormer.Update(&user, "Langs", "Extra") - Update(md interface{}, cols ...string) (int64, error) - // Delete delete model in database - Delete(md interface{}, cols ...string) (int64, error) - // LoadRelated load related models to md model. - // args are limit, offset int and order string. - // - // example: - // Ormer.LoadRelated(post,"Tags") - // for _,tag := range post.Tags{...} - // args[0] bool true useDefaultRelsDepth ; false depth 0 - // args[0] int loadRelationDepth - // args[1] int limit default limit 1000 - // args[2] int offset default offset 0 - // args[3] string order for example : "-Id" - // make sure the relation is defined in model struct tags. - LoadRelated(md interface{}, name string, args ...interface{}) (int64, error) - // QueryM2M create a models to models queryer - // for example: - // post := Post{Id: 4} - // m2m := Ormer.QueryM2M(&post, "Tags") - QueryM2M(md interface{}, name string) QueryM2Mer - // QueryTable return a QuerySeter for table operations. - // table name can be string or struct. - // e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)), - QueryTable(ptrStructOrTableName interface{}) QuerySeter - // switch to another registered database driver by given name. - Using(name string) error - // Begin begin transaction - // for example: - // o := NewOrm() - // err := o.Begin() - // ... - // err = o.Rollback() - Begin() error - // BeginTx begin transaction with provided context and option - // the provided context is used until the transaction is committed or rolled back. - // if the context is canceled, the transaction will be rolled back. - // the provided TxOptions is optional and may be nil if defaults should be used. - // if a non-default isolation level is used that the driver doesn't support, an error will be returned. - // for example: - // o := NewOrm() - // err := o.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead}) - // ... - // err = o.Rollback() - BeginTx(ctx context.Context, opts *sql.TxOptions) error - // Commit commit transaction - Commit() error - // Rollback rollback transaction - Rollback() error - // Raw return a raw query seter for raw sql string. - // for example: - // ormer.Raw("UPDATE `user` SET `user_name` = ? WHERE `user_name` = ?", "slene", "testing").Exec() - // // update user testing's name to slene - Raw(query string, args ...interface{}) RawSeter - Driver() Driver - DBStats() *sql.DBStats -} - -// Inserter insert prepared statement -type Inserter orm.Inserter - -// QuerySeter query seter -type QuerySeter orm.QuerySeter - -// QueryM2Mer model to model query struct -// all operations are on the m2m table only, will not affect the origin model table -type QueryM2Mer orm.QueryM2Mer - -// RawPreparer raw query statement -type RawPreparer orm.RawPreparer - -// RawSeter raw query seter -// create From Ormer.Raw -// for example: -// sql := fmt.Sprintf("SELECT %sid%s,%sname%s FROM %suser%s WHERE id = ?",Q,Q,Q,Q,Q,Q) -// rs := Ormer.Raw(sql, 1) -type RawSeter orm.RawSeter diff --git a/adapter/orm/utils.go b/adapter/orm/utils.go deleted file mode 100644 index a88836c3..00000000 --- a/adapter/orm/utils.go +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "fmt" - "reflect" - "strconv" - "strings" - "time" - - "github.com/beego/beego/v2/client/orm" -) - -type fn func(string) string - -var ( - nameStrategyMap = map[string]fn{ - defaultNameStrategy: snakeString, - SnakeAcronymNameStrategy: snakeStringWithAcronym, - } - defaultNameStrategy = "snakeString" - SnakeAcronymNameStrategy = "snakeStringWithAcronym" - nameStrategy = defaultNameStrategy -) - -// StrTo is the target string -type StrTo orm.StrTo - -// Set string -func (f *StrTo) Set(v string) { - (*orm.StrTo)(f).Set(v) -} - -// Clear string -func (f *StrTo) Clear() { - (*orm.StrTo)(f).Clear() -} - -// Exist check string exist -func (f StrTo) Exist() bool { - return orm.StrTo(f).Exist() -} - -// Bool string to bool -func (f StrTo) Bool() (bool, error) { - return orm.StrTo(f).Bool() -} - -// Float32 string to float32 -func (f StrTo) Float32() (float32, error) { - return orm.StrTo(f).Float32() -} - -// Float64 string to float64 -func (f StrTo) Float64() (float64, error) { - return orm.StrTo(f).Float64() -} - -// Int string to int -func (f StrTo) Int() (int, error) { - return orm.StrTo(f).Int() -} - -// Int8 string to int8 -func (f StrTo) Int8() (int8, error) { - return orm.StrTo(f).Int8() -} - -// Int16 string to int16 -func (f StrTo) Int16() (int16, error) { - return orm.StrTo(f).Int16() -} - -// Int32 string to int32 -func (f StrTo) Int32() (int32, error) { - return orm.StrTo(f).Int32() -} - -// Int64 string to int64 -func (f StrTo) Int64() (int64, error) { - return orm.StrTo(f).Int64() -} - -// Uint string to uint -func (f StrTo) Uint() (uint, error) { - return orm.StrTo(f).Uint() -} - -// Uint8 string to uint8 -func (f StrTo) Uint8() (uint8, error) { - return orm.StrTo(f).Uint8() -} - -// Uint16 string to uint16 -func (f StrTo) Uint16() (uint16, error) { - return orm.StrTo(f).Uint16() -} - -// Uint32 string to uint32 -func (f StrTo) Uint32() (uint32, error) { - return orm.StrTo(f).Uint32() -} - -// Uint64 string to uint64 -func (f StrTo) Uint64() (uint64, error) { - return orm.StrTo(f).Uint64() -} - -// String string to string -func (f StrTo) String() string { - return orm.StrTo(f).String() -} - -// ToStr interface to string -func ToStr(value interface{}, args ...int) (s string) { - switch v := value.(type) { - case bool: - s = strconv.FormatBool(v) - case float32: - s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32)) - case float64: - s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64)) - case int: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int8: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int16: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int32: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int64: - s = strconv.FormatInt(v, argInt(args).Get(0, 10)) - case uint: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint8: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint16: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint32: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint64: - s = strconv.FormatUint(v, argInt(args).Get(0, 10)) - case string: - s = v - case []byte: - s = string(v) - default: - s = fmt.Sprintf("%v", v) - } - return s -} - -// ToInt64 interface to int64 -func ToInt64(value interface{}) (d int64) { - val := reflect.ValueOf(value) - switch value.(type) { - case int, int8, int16, int32, int64: - d = val.Int() - case uint, uint8, uint16, uint32, uint64: - d = int64(val.Uint()) - default: - panic(fmt.Errorf("ToInt64 need numeric not `%T`", value)) - } - return -} - -func snakeStringWithAcronym(s string) string { - data := make([]byte, 0, len(s)*2) - num := len(s) - for i := 0; i < num; i++ { - d := s[i] - before := false - after := false - if i > 0 { - before = s[i-1] >= 'a' && s[i-1] <= 'z' - } - if i+1 < num { - after = s[i+1] >= 'a' && s[i+1] <= 'z' - } - if i > 0 && d >= 'A' && d <= 'Z' && (before || after) { - data = append(data, '_') - } - data = append(data, d) - } - return strings.ToLower(string(data)) -} - -// snake string, XxYy to xx_yy , XxYY to xx_y_y -func snakeString(s string) string { - data := make([]byte, 0, len(s)*2) - j := false - num := len(s) - for i := 0; i < num; i++ { - d := s[i] - if i > 0 && d >= 'A' && d <= 'Z' && j { - data = append(data, '_') - } - if d != '_' { - j = true - } - data = append(data, d) - } - return strings.ToLower(string(data)) -} - -// SetNameStrategy set different name strategy -func SetNameStrategy(s string) { - if SnakeAcronymNameStrategy != s { - nameStrategy = defaultNameStrategy - } - nameStrategy = s -} - -// camel string, xx_yy to XxYy -func camelString(s string) string { - data := make([]byte, 0, len(s)) - flag, num := true, len(s)-1 - for i := 0; i <= num; i++ { - d := s[i] - if d == '_' { - flag = true - continue - } else if flag { - if d >= 'a' && d <= 'z' { - d = d - 32 - } - flag = false - } - data = append(data, d) - } - return string(data) -} - -type argString []string - -// Get will get string by index from string slice -func (a argString) Get(i int, args ...string) (r string) { - if i >= 0 && i < len(a) { - r = a[i] - } else if len(args) > 0 { - r = args[0] - } - return -} - -type argInt []int - -// Get will get int by index from int slice -func (a argInt) Get(i int, args ...int) (r int) { - if i >= 0 && i < len(a) { - r = a[i] - } - if len(args) > 0 { - r = args[0] - } - return -} - -// timeParse parse time to string with location -func timeParse(dateString, format string) (time.Time, error) { - tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) - return tp, err -} - -// indirectType get pointer indirect type -func indirectType(v reflect.Type) reflect.Type { - switch v.Kind() { - case reflect.Ptr: - return indirectType(v.Elem()) - default: - return v - } -} diff --git a/adapter/orm/utils_test.go b/adapter/orm/utils_test.go deleted file mode 100644 index fbf8663e..00000000 --- a/adapter/orm/utils_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestCamelString(t *testing.T) { - snake := []string{"pic_url", "hello_world_", "hello__World", "_HelLO_Word", "pic_url_1", "pic_url__1"} - camel := []string{"PicUrl", "HelloWorld", "HelloWorld", "HelLOWord", "PicUrl1", "PicUrl1"} - - answer := make(map[string]string) - for i, v := range snake { - answer[v] = camel[i] - } - - for _, v := range snake { - res := camelString(v) - assert.Equal(t, answer[v], res) - } -} - -func TestSnakeString(t *testing.T) { - camel := []string{"PicUrl", "HelloWorld", "HelloWorld", "HelLOWord", "PicUrl1", "XyXX"} - snake := []string{"pic_url", "hello_world", "hello_world", "hel_l_o_word", "pic_url1", "xy_x_x"} - - answer := make(map[string]string) - for i, v := range camel { - answer[v] = snake[i] - } - - for _, v := range camel { - res := snakeString(v) - assert.Equal(t, answer[v], res) - } -} - -func TestSnakeStringWithAcronym(t *testing.T) { - camel := []string{"ID", "PicURL", "HelloWorld", "HelloWorld", "HelLOWord", "PicUrl1", "XyXX"} - snake := []string{"id", "pic_url", "hello_world", "hello_world", "hel_lo_word", "pic_url1", "xy_xx"} - - answer := make(map[string]string) - for i, v := range camel { - answer[v] = snake[i] - } - - for _, v := range camel { - res := snakeStringWithAcronym(v) - assert.Equal(t, answer[v], res) - } -} diff --git a/adapter/plugins/apiauth/apiauth.go b/adapter/plugins/apiauth/apiauth.go deleted file mode 100644 index d5511427..00000000 --- a/adapter/plugins/apiauth/apiauth.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package apiauth provides handlers to enable apiauth support. -// -// Simple Usage: -// import( -// "github.com/beego/beego/v2" -// "github.com/beego/beego/v2/server/web/filter/apiauth" -// ) -// -// func main(){ -// // apiauth every request -// beego.InsertFilter("*", beego.BeforeRouter,apiauth.APIBaiscAuth("appid","appkey")) -// beego.Run() -// } -// -// Advanced Usage: -// -// func getAppSecret(appid string) string { -// // get appsecret by appid -// // maybe store in configure, maybe in database -// } -// -// beego.InsertFilter("*", beego.BeforeRouter,apiauth.APISecretAuth(getAppSecret, 360)) -// -// Information: -// -// In the request user should include these params in the query -// -// 1. appid -// -// appid is assigned to the application -// -// 2. signature -// -// get the signature use apiauth.Signature() -// -// when you send to server remember use url.QueryEscape() -// -// 3. timestamp: -// -// send the request time, the format is yyyy-mm-dd HH:ii:ss -// -package apiauth - -import ( - "net/url" - - beego "github.com/beego/beego/v2/adapter" - "github.com/beego/beego/v2/adapter/context" - beecontext "github.com/beego/beego/v2/server/web/context" - "github.com/beego/beego/v2/server/web/filter/apiauth" -) - -// AppIDToAppSecret is used to get appsecret throw appid -type AppIDToAppSecret apiauth.AppIDToAppSecret - -// APIBasicAuth use the basic appid/appkey as the AppIdToAppSecret -func APIBasicAuth(appid, appkey string) beego.FilterFunc { - f := apiauth.APIBasicAuth(appid, appkey) - return func(c *context.Context) { - f((*beecontext.Context)(c)) - } -} - -// APIBaiscAuth calls APIBasicAuth for previous callers -func APIBaiscAuth(appid, appkey string) beego.FilterFunc { - return APIBasicAuth(appid, appkey) -} - -// APISecretAuth use AppIdToAppSecret verify and -func APISecretAuth(f AppIDToAppSecret, timeout int) beego.FilterFunc { - ft := apiauth.APISecretAuth(apiauth.AppIDToAppSecret(f), timeout) - return func(ctx *context.Context) { - ft((*beecontext.Context)(ctx)) - } -} - -// Signature used to generate signature with the appsecret/method/params/RequestURI -func Signature(appsecret, method string, params url.Values, requestURL string) string { - return apiauth.Signature(appsecret, method, params, requestURL) -} diff --git a/adapter/plugins/apiauth/apiauth_test.go b/adapter/plugins/apiauth/apiauth_test.go deleted file mode 100644 index 1f56cb0f..00000000 --- a/adapter/plugins/apiauth/apiauth_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package apiauth - -import ( - "net/url" - "testing" -) - -func TestSignature(t *testing.T) { - appsecret := "beego secret" - method := "GET" - RequestURL := "http://localhost/test/url" - params := make(url.Values) - params.Add("arg1", "hello") - params.Add("arg2", "beego") - - signature := "mFdpvLh48ca4mDVEItE9++AKKQ/IVca7O/ZyyB8hR58=" - if Signature(appsecret, method, params, RequestURL) != signature { - t.Error("Signature error") - } -} diff --git a/adapter/plugins/auth/basic.go b/adapter/plugins/auth/basic.go deleted file mode 100644 index 173252ca..00000000 --- a/adapter/plugins/auth/basic.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package auth provides handlers to enable basic auth support. -// Simple Usage: -// import( -// "github.com/beego/beego/v2" -// "github.com/beego/beego/v2/server/web/filter/auth" -// ) -// -// func main(){ -// // authenticate every request -// beego.InsertFilter("*", beego.BeforeRouter,auth.Basic("username","secretpassword")) -// beego.Run() -// } -// -// -// Advanced Usage: -// -// func SecretAuth(username, password string) bool { -// return username == "astaxie" && password == "helloBeego" -// } -// authPlugin := auth.NewBasicAuthenticator(SecretAuth, "Authorization Required") -// beego.InsertFilter("*", beego.BeforeRouter,authPlugin) -package auth - -import ( - "net/http" - - beego "github.com/beego/beego/v2/adapter" - "github.com/beego/beego/v2/adapter/context" - beecontext "github.com/beego/beego/v2/server/web/context" - "github.com/beego/beego/v2/server/web/filter/auth" -) - -// Basic is the http basic auth -func Basic(username string, password string) beego.FilterFunc { - return func(c *context.Context) { - f := auth.Basic(username, password) - f((*beecontext.Context)(c)) - } -} - -// NewBasicAuthenticator return the BasicAuth -func NewBasicAuthenticator(secrets SecretProvider, realm string) beego.FilterFunc { - f := auth.NewBasicAuthenticator(auth.SecretProvider(secrets), realm) - return func(c *context.Context) { - f((*beecontext.Context)(c)) - } -} - -// SecretProvider is the SecretProvider function -type SecretProvider auth.SecretProvider - -// BasicAuth store the SecretProvider and Realm -type BasicAuth auth.BasicAuth - -// CheckAuth Checks the username/password combination from the request. Returns -// either an empty string (authentication failed) or the name of the -// authenticated user. -// Supports MD5 and SHA1 password entries -func (a *BasicAuth) CheckAuth(r *http.Request) string { - return (*auth.BasicAuth)(a).CheckAuth(r) -} - -// RequireAuth http.Handler for BasicAuth which initiates the authentication process -// (or requires reauthentication). -func (a *BasicAuth) RequireAuth(w http.ResponseWriter, r *http.Request) { - (*auth.BasicAuth)(a).RequireAuth(w, r) -} diff --git a/adapter/plugins/authz/authz.go b/adapter/plugins/authz/authz.go deleted file mode 100644 index 096d7efb..00000000 --- a/adapter/plugins/authz/authz.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package authz provides handlers to enable ACL, RBAC, ABAC authorization support. -// Simple Usage: -// import( -// "github.com/beego/beego/v2" -// "github.com/beego/beego/v2/server/web/filter/authz" -// "github.com/casbin/casbin" -// ) -// -// func main(){ -// // mediate the access for every request -// beego.InsertFilter("*", beego.BeforeRouter, authz.NewAuthorizer(casbin.NewEnforcer("authz_model.conf", "authz_policy.csv"))) -// beego.Run() -// } -// -// -// Advanced Usage: -// -// func main(){ -// e := casbin.NewEnforcer("authz_model.conf", "") -// e.AddRoleForUser("alice", "admin") -// e.AddPolicy(...) -// -// beego.InsertFilter("*", beego.BeforeRouter, authz.NewAuthorizer(e)) -// beego.Run() -// } -package authz - -import ( - "net/http" - - "github.com/casbin/casbin" - - beego "github.com/beego/beego/v2/adapter" - "github.com/beego/beego/v2/adapter/context" - beecontext "github.com/beego/beego/v2/server/web/context" - "github.com/beego/beego/v2/server/web/filter/authz" -) - -// NewAuthorizer returns the authorizer. -// Use a casbin enforcer as input -func NewAuthorizer(e *casbin.Enforcer) beego.FilterFunc { - f := authz.NewAuthorizer(e) - return func(context *context.Context) { - f((*beecontext.Context)(context)) - } -} - -// BasicAuthorizer stores the casbin handler -type BasicAuthorizer authz.BasicAuthorizer - -// GetUserName gets the user name from the request. -// Currently, only HTTP basic authentication is supported -func (a *BasicAuthorizer) GetUserName(r *http.Request) string { - return (*authz.BasicAuthorizer)(a).GetUserName(r) -} - -// CheckPermission checks the user/method/path combination from the request. -// Returns true (permission granted) or false (permission forbidden) -func (a *BasicAuthorizer) CheckPermission(r *http.Request) bool { - return (*authz.BasicAuthorizer)(a).CheckPermission(r) -} - -// RequirePermission returns the 403 Forbidden to the client -func (a *BasicAuthorizer) RequirePermission(w http.ResponseWriter) { - (*authz.BasicAuthorizer)(a).RequirePermission(w) -} diff --git a/adapter/plugins/authz/authz_model.conf b/adapter/plugins/authz/authz_model.conf deleted file mode 100644 index fd2f08df..00000000 --- a/adapter/plugins/authz/authz_model.conf +++ /dev/null @@ -1,14 +0,0 @@ -[request_definition] -r = sub, obj, act - -[policy_definition] -p = sub, obj, act - -[role_definition] -g = _, _ - -[policy_effect] -e = some(where (p.eft == allow)) - -[matchers] -m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*") diff --git a/adapter/plugins/authz/authz_policy.csv b/adapter/plugins/authz/authz_policy.csv deleted file mode 100644 index 9203e11f..00000000 --- a/adapter/plugins/authz/authz_policy.csv +++ /dev/null @@ -1,7 +0,0 @@ -p, alice, /dataset1/*, GET -p, alice, /dataset1/resource1, POST -p, bob, /dataset2/resource1, * -p, bob, /dataset2/resource2, GET -p, bob, /dataset2/folder1/*, POST -p, dataset1_admin, /dataset1/*, * -g, cathy, dataset1_admin diff --git a/adapter/plugins/authz/authz_test.go b/adapter/plugins/authz/authz_test.go deleted file mode 100644 index 4963ceab..00000000 --- a/adapter/plugins/authz/authz_test.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package authz - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/casbin/casbin" - - beego "github.com/beego/beego/v2/adapter" - "github.com/beego/beego/v2/adapter/context" - "github.com/beego/beego/v2/adapter/plugins/auth" -) - -const ( - authCfg = "authz_model.conf" - authCsv = "authz_policy.csv" -) - -func testRequest(t *testing.T, handler *beego.ControllerRegister, user string, path string, method string, code int) { - r, _ := http.NewRequest(method, path, nil) - r.SetBasicAuth(user, "123") - w := httptest.NewRecorder() - handler.ServeHTTP(w, r) - - if w.Code != code { - t.Errorf("%s, %s, %s: %d, supposed to be %d", user, path, method, w.Code, code) - } -} - -func TestBasic(t *testing.T) { - handler := beego.NewControllerRegister() - - _ = handler.InsertFilter("*", beego.BeforeRouter, auth.Basic("alice", "123")) - - _ = handler.InsertFilter("*", beego.BeforeRouter, NewAuthorizer(casbin.NewEnforcer(authCfg, authCsv))) - - handler.Any("*", func(ctx *context.Context) { - ctx.Output.SetStatus(200) - }) - - const d1r1 = "/dataset1/resource1" - testRequest(t, handler, "alice", d1r1, "GET", 200) - testRequest(t, handler, "alice", d1r1, "POST", 200) - const d1r2 = "/dataset1/resource2" - testRequest(t, handler, "alice", d1r2, "GET", 200) - testRequest(t, handler, "alice", d1r2, "POST", 403) -} - -func TestPathWildcard(t *testing.T) { - handler := beego.NewControllerRegister() - - _ = handler.InsertFilter("*", beego.BeforeRouter, auth.Basic("bob", "123")) - _ = handler.InsertFilter("*", beego.BeforeRouter, NewAuthorizer(casbin.NewEnforcer(authCfg, authCsv))) - - handler.Any("*", func(ctx *context.Context) { - ctx.Output.SetStatus(200) - }) - - const d2r1 = "/dataset2/resource1" - testRequest(t, handler, "bob", d2r1, "GET", 200) - testRequest(t, handler, "bob", d2r1, "POST", 200) - testRequest(t, handler, "bob", d2r1, "DELETE", 200) - const d2r2 = "/dataset2/resource2" - testRequest(t, handler, "bob", d2r2, "GET", 200) - testRequest(t, handler, "bob", d2r2, "POST", 403) - testRequest(t, handler, "bob", d2r2, "DELETE", 403) - - const item1 = "/dataset2/folder1/item1" - testRequest(t, handler, "bob", item1, "GET", 403) - testRequest(t, handler, "bob", item1, "POST", 200) - testRequest(t, handler, "bob", item1, "DELETE", 403) - const item2 = "/dataset2/folder1/item2" - testRequest(t, handler, "bob", item2, "GET", 403) - testRequest(t, handler, "bob", item2, "POST", 200) - testRequest(t, handler, "bob", item2, "DELETE", 403) -} - -func TestRBAC(t *testing.T) { - handler := beego.NewControllerRegister() - - _ = handler.InsertFilter("*", beego.BeforeRouter, auth.Basic("cathy", "123")) - e := casbin.NewEnforcer(authCfg, authCsv) - _ = handler.InsertFilter("*", beego.BeforeRouter, NewAuthorizer(e)) - - handler.Any("*", func(ctx *context.Context) { - ctx.Output.SetStatus(200) - }) - - // cathy can access all /dataset1/* resources via all methods because it has the dataset1_admin role. - const dataSet1 = "/dataset1/item" - testRequest(t, handler, "cathy", dataSet1, "GET", 200) - testRequest(t, handler, "cathy", dataSet1, "POST", 200) - testRequest(t, handler, "cathy", dataSet1, "DELETE", 200) - const dataSet2 = "/dataset2/item" - testRequest(t, handler, "cathy", dataSet2, "GET", 403) - testRequest(t, handler, "cathy", dataSet2, "POST", 403) - testRequest(t, handler, "cathy", dataSet2, "DELETE", 403) - - // delete all roles on user cathy, so cathy cannot access any resources now. - e.DeleteRolesForUser("cathy") - - testRequest(t, handler, "cathy", dataSet1, "GET", 403) - testRequest(t, handler, "cathy", dataSet1, "POST", 403) - testRequest(t, handler, "cathy", dataSet1, "DELETE", 403) - testRequest(t, handler, "cathy", dataSet2, "GET", 403) - testRequest(t, handler, "cathy", dataSet2, "POST", 403) - testRequest(t, handler, "cathy", dataSet2, "DELETE", 403) -} diff --git a/adapter/plugins/cors/cors.go b/adapter/plugins/cors/cors.go deleted file mode 100644 index c02ab877..00000000 --- a/adapter/plugins/cors/cors.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package cors provides handlers to enable CORS support. -// Usage -// import ( -// "github.com/beego/beego/v2" -// "github.com/beego/beego/v2/server/web/filter/cors" -// ) -// -// func main() { -// // CORS for https://foo.* origins, allowing: -// // - PUT and PATCH methods -// // - Origin header -// // - Credentials share -// beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{ -// AllowOrigins: []string{"https://*.foo.com"}, -// AllowMethods: []string{"PUT", "PATCH"}, -// AllowHeaders: []string{"Origin"}, -// ExposeHeaders: []string{"Content-Length"}, -// AllowCredentials: true, -// })) -// beego.Run() -// } -package cors - -import ( - beego "github.com/beego/beego/v2/adapter" - "github.com/beego/beego/v2/adapter/context" - beecontext "github.com/beego/beego/v2/server/web/context" - "github.com/beego/beego/v2/server/web/filter/cors" -) - -// Options represents Access Control options. -type Options cors.Options - -// Header converts options into CORS headers. -func (o *Options) Header(origin string) (headers map[string]string) { - return (*cors.Options)(o).Header(origin) -} - -// PreflightHeader converts options into CORS headers for a preflight response. -func (o *Options) PreflightHeader(origin, rMethod, rHeaders string) (headers map[string]string) { - return (*cors.Options)(o).PreflightHeader(origin, rMethod, rHeaders) -} - -// IsOriginAllowed looks up if the origin matches one of the patterns -// generated from Options.AllowOrigins patterns. -func (o *Options) IsOriginAllowed(origin string) bool { - return (*cors.Options)(o).IsOriginAllowed(origin) -} - -// Allow enables CORS for requests those match the provided options. -func Allow(opts *Options) beego.FilterFunc { - f := cors.Allow((*cors.Options)(opts)) - return func(c *context.Context) { - f((*beecontext.Context)(c)) - } -} diff --git a/adapter/policy.go b/adapter/policy.go deleted file mode 100644 index c0b95601..00000000 --- a/adapter/policy.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2016 beego authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "github.com/beego/beego/v2/adapter/context" - "github.com/beego/beego/v2/server/web" - beecontext "github.com/beego/beego/v2/server/web/context" -) - -// PolicyFunc defines a policy function which is invoked before the controller handler is executed. -type PolicyFunc func(*context.Context) - -// FindPolicy Find Router info for URL -func (p *ControllerRegister) FindPolicy(cont *context.Context) []PolicyFunc { - pf := (*web.ControllerRegister)(p).FindPolicy((*beecontext.Context)(cont)) - npf := newToOldPolicyFunc(pf) - return npf -} - -func newToOldPolicyFunc(pf []web.PolicyFunc) []PolicyFunc { - npf := make([]PolicyFunc, 0, len(pf)) - for _, f := range pf { - npf = append(npf, func(c *context.Context) { - f((*beecontext.Context)(c)) - }) - } - return npf -} - -func oldToNewPolicyFunc(pf []PolicyFunc) []web.PolicyFunc { - npf := make([]web.PolicyFunc, 0, len(pf)) - for _, f := range pf { - npf = append(npf, func(c *beecontext.Context) { - f((*context.Context)(c)) - }) - } - return npf -} - -// Policy Register new policy in beego -func Policy(pattern, method string, policy ...PolicyFunc) { - pf := oldToNewPolicyFunc(policy) - web.Policy(pattern, method, pf...) -} diff --git a/adapter/router.go b/adapter/router.go deleted file mode 100644 index 23f08e1e..00000000 --- a/adapter/router.go +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "net/http" - "time" - - beecontext "github.com/beego/beego/v2/adapter/context" - "github.com/beego/beego/v2/server/web" - "github.com/beego/beego/v2/server/web/context" -) - -// default filter execution points -const ( - BeforeStatic = web.BeforeStatic - BeforeRouter = web.BeforeRouter - BeforeExec = web.BeforeExec - AfterExec = web.AfterExec - FinishRouter = web.FinishRouter -) - -var ( - // HTTPMETHOD list the supported http methods. - HTTPMETHOD = web.HTTPMETHOD - - // DefaultAccessLogFilter will skip the accesslog if return true - DefaultAccessLogFilter FilterHandler = &newToOldFtHdlAdapter{ - delegate: web.DefaultAccessLogFilter, - } -) - -// FilterHandler is an interface for -type FilterHandler interface { - Filter(*beecontext.Context) bool -} - -type newToOldFtHdlAdapter struct { - delegate web.FilterHandler -} - -func (n *newToOldFtHdlAdapter) Filter(ctx *beecontext.Context) bool { - return n.delegate.Filter((*context.Context)(ctx)) -} - -// ExceptMethodAppend to append a slice's value into "exceptMethod", for controller's methods shouldn't reflect to AutoRouter -func ExceptMethodAppend(action string) { - web.ExceptMethodAppend(action) -} - -// ControllerInfo holds information about the controller. -type ControllerInfo web.ControllerInfo - -func (c *ControllerInfo) GetPattern() string { - return (*web.ControllerInfo)(c).GetPattern() -} - -// ControllerRegister containers registered router rules, controller handlers and filters. -type ControllerRegister web.ControllerRegister - -// NewControllerRegister returns a new ControllerRegister. -func NewControllerRegister() *ControllerRegister { - return (*ControllerRegister)(web.NewControllerRegister()) -} - -// Add controller handler and pattern rules to ControllerRegister. -// usage: -// default methods is the same name as method -// Add("/user",&UserController{}) -// Add("/api/list",&RestController{},"*:ListFood") -// Add("/api/create",&RestController{},"post:CreateFood") -// Add("/api/update",&RestController{},"put:UpdateFood") -// Add("/api/delete",&RestController{},"delete:DeleteFood") -// Add("/api",&RestController{},"get,post:ApiFunc" -// Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc") -func (p *ControllerRegister) Add(pattern string, c ControllerInterface, mappingMethods ...string) { - (*web.ControllerRegister)(p).Add(pattern, c, web.WithRouterMethods(c, mappingMethods...)) -} - -// Include only when the Runmode is dev will generate router file in the router/auto.go from the controller -// Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{}) -func (p *ControllerRegister) Include(cList ...ControllerInterface) { - nls := oldToNewCtrlIntfs(cList) - (*web.ControllerRegister)(p).Include(nls...) -} - -// GetContext returns a context from pool, so usually you should remember to call Reset function to clean the context -// And don't forget to give back context to pool -// example: -// ctx := p.GetContext() -// ctx.Reset(w, q) -// defer p.GiveBackContext(ctx) -func (p *ControllerRegister) GetContext() *beecontext.Context { - return (*beecontext.Context)((*web.ControllerRegister)(p).GetContext()) -} - -// GiveBackContext put the ctx into pool so that it could be reuse -func (p *ControllerRegister) GiveBackContext(ctx *beecontext.Context) { - (*web.ControllerRegister)(p).GiveBackContext((*context.Context)(ctx)) -} - -// Get add get method -// usage: -// Get("/", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func (p *ControllerRegister) Get(pattern string, f FilterFunc) { - (*web.ControllerRegister)(p).Get(pattern, func(ctx *context.Context) { - f((*beecontext.Context)(ctx)) - }) -} - -// Post add post method -// usage: -// Post("/api", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func (p *ControllerRegister) Post(pattern string, f FilterFunc) { - (*web.ControllerRegister)(p).Post(pattern, func(ctx *context.Context) { - f((*beecontext.Context)(ctx)) - }) -} - -// Put add put method -// usage: -// Put("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func (p *ControllerRegister) Put(pattern string, f FilterFunc) { - (*web.ControllerRegister)(p).Put(pattern, func(ctx *context.Context) { - f((*beecontext.Context)(ctx)) - }) -} - -// Delete add delete method -// usage: -// Delete("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func (p *ControllerRegister) Delete(pattern string, f FilterFunc) { - (*web.ControllerRegister)(p).Delete(pattern, func(ctx *context.Context) { - f((*beecontext.Context)(ctx)) - }) -} - -// Head add head method -// usage: -// Head("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func (p *ControllerRegister) Head(pattern string, f FilterFunc) { - (*web.ControllerRegister)(p).Head(pattern, func(ctx *context.Context) { - f((*beecontext.Context)(ctx)) - }) -} - -// Patch add patch method -// usage: -// Patch("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func (p *ControllerRegister) Patch(pattern string, f FilterFunc) { - (*web.ControllerRegister)(p).Patch(pattern, func(ctx *context.Context) { - f((*beecontext.Context)(ctx)) - }) -} - -// Options add options method -// usage: -// Options("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func (p *ControllerRegister) Options(pattern string, f FilterFunc) { - (*web.ControllerRegister)(p).Options(pattern, func(ctx *context.Context) { - f((*beecontext.Context)(ctx)) - }) -} - -// Any add all method -// usage: -// Any("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func (p *ControllerRegister) Any(pattern string, f FilterFunc) { - (*web.ControllerRegister)(p).Any(pattern, func(ctx *context.Context) { - f((*beecontext.Context)(ctx)) - }) -} - -// AddMethod add http method router -// usage: -// AddMethod("get","/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) -func (p *ControllerRegister) AddMethod(method, pattern string, f FilterFunc) { - (*web.ControllerRegister)(p).AddMethod(method, pattern, func(ctx *context.Context) { - f((*beecontext.Context)(ctx)) - }) -} - -// Handler add user defined Handler -func (p *ControllerRegister) Handler(pattern string, h http.Handler, options ...interface{}) { - (*web.ControllerRegister)(p).Handler(pattern, h, options...) -} - -// AddAuto router to ControllerRegister. -// example beego.AddAuto(&MainController{}), -// MainController has method List and Page. -// visit the url /main/list to execute List function -// /main/page to execute Page function. -func (p *ControllerRegister) AddAuto(c ControllerInterface) { - (*web.ControllerRegister)(p).AddAuto(c) -} - -// AddAutoPrefix Add auto router to ControllerRegister with prefix. -// example beego.AddAutoPrefix("/admin",&MainController{}), -// MainController has method List and Page. -// visit the url /admin/main/list to execute List function -// /admin/main/page to execute Page function. -func (p *ControllerRegister) AddAutoPrefix(prefix string, c ControllerInterface) { - (*web.ControllerRegister)(p).AddAutoPrefix(prefix, c) -} - -// InsertFilter Add a FilterFunc with pattern rule and action constant. -// params is for: -// 1. setting the returnOnOutput value (false allows multiple filters to execute) -// 2. determining whether or not params need to be reset. -func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) error { - opts := oldToNewFilterOpts(params) - return (*web.ControllerRegister)(p).InsertFilter(pattern, pos, func(ctx *context.Context) { - filter((*beecontext.Context)(ctx)) - }, opts...) -} - -func oldToNewFilterOpts(params []bool) []web.FilterOpt { - opts := make([]web.FilterOpt, 0, 4) - if len(params) > 0 { - opts = append(opts, web.WithReturnOnOutput(params[0])) - } else { - // the default value should be true - opts = append(opts, web.WithReturnOnOutput(true)) - } - if len(params) > 1 { - opts = append(opts, web.WithResetParams(params[1])) - } - return opts -} - -// URLFor does another controller handler in this request function. -// it can access any controller method. -func (p *ControllerRegister) URLFor(endpoint string, values ...interface{}) string { - return (*web.ControllerRegister)(p).URLFor(endpoint, values...) -} - -// Implement http.Handler interface. -func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) { - (*web.ControllerRegister)(p).ServeHTTP(rw, r) -} - -// FindRouter Find Router info for URL -func (p *ControllerRegister) FindRouter(ctx *beecontext.Context) (routerInfo *ControllerInfo, isFind bool) { - r, ok := (*web.ControllerRegister)(p).FindRouter((*context.Context)(ctx)) - return (*ControllerInfo)(r), ok -} - -// LogAccess logging info HTTP Access -func LogAccess(ctx *beecontext.Context, startTime *time.Time, statusCode int) { - web.LogAccess((*context.Context)(ctx), startTime, statusCode) -} diff --git a/adapter/session/couchbase/sess_couchbase.go b/adapter/session/couchbase/sess_couchbase.go deleted file mode 100644 index 9e37e56b..00000000 --- a/adapter/session/couchbase/sess_couchbase.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package couchbase for session provider -// -// depend on github.com/couchbaselabs/go-couchbasee -// -// go install github.com/couchbaselabs/go-couchbase -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/server/web/session/couchbase" -// "github.com/beego/beego/v2/server/web/session" -// ) -// -// func init() { -// globalSessions, _ = session.NewManager("couchbase", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"http://host:port/, Pool, Bucket"}``) -// go globalSessions.GC() -// } -// -package couchbase - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/adapter/session" - beecb "github.com/beego/beego/v2/server/web/session/couchbase" -) - -// SessionStore store each session -type SessionStore beecb.SessionStore - -// Provider couchabse provided -type Provider beecb.Provider - -// Set value to couchabse session -func (cs *SessionStore) Set(key, value interface{}) error { - return (*beecb.SessionStore)(cs).Set(context.Background(), key, value) -} - -// Get value from couchabse session -func (cs *SessionStore) Get(key interface{}) interface{} { - return (*beecb.SessionStore)(cs).Get(context.Background(), key) -} - -// Delete value in couchbase session by given key -func (cs *SessionStore) Delete(key interface{}) error { - return (*beecb.SessionStore)(cs).Delete(context.Background(), key) -} - -// Flush Clean all values in couchbase session -func (cs *SessionStore) Flush() error { - return (*beecb.SessionStore)(cs).Flush(context.Background()) -} - -// SessionID Get couchbase session store id -func (cs *SessionStore) SessionID() string { - return (*beecb.SessionStore)(cs).SessionID(context.Background()) -} - -// SessionRelease Write couchbase session with Gob string -func (cs *SessionStore) SessionRelease(w http.ResponseWriter) { - (*beecb.SessionStore)(cs).SessionRelease(context.Background(), w) -} - -// SessionInit init couchbase session -// savepath like couchbase server REST/JSON URL -// e.g. http://host:port/, Pool, Bucket -func (cp *Provider) SessionInit(maxlifetime int64, savePath string) error { - return (*beecb.Provider)(cp).SessionInit(context.Background(), maxlifetime, savePath) -} - -// SessionRead read couchbase session by sid -func (cp *Provider) SessionRead(sid string) (session.Store, error) { - s, err := (*beecb.Provider)(cp).SessionRead(context.Background(), sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionExist Check couchbase session exist. -// it checkes sid exist or not. -func (cp *Provider) SessionExist(sid string) bool { - res, _ := (*beecb.Provider)(cp).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate remove oldsid and use sid to generate new session -func (cp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { - s, err := (*beecb.Provider)(cp).SessionRegenerate(context.Background(), oldsid, sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionDestroy Remove bucket in this couchbase -func (cp *Provider) SessionDestroy(sid string) error { - return (*beecb.Provider)(cp).SessionDestroy(context.Background(), sid) -} - -// SessionGC Recycle -func (cp *Provider) SessionGC() { - (*beecb.Provider)(cp).SessionGC(context.Background()) -} - -// SessionAll return all active session -func (cp *Provider) SessionAll() int { - return (*beecb.Provider)(cp).SessionAll(context.Background()) -} diff --git a/adapter/session/ledis/ledis_session.go b/adapter/session/ledis/ledis_session.go deleted file mode 100644 index c42c1787..00000000 --- a/adapter/session/ledis/ledis_session.go +++ /dev/null @@ -1,86 +0,0 @@ -// Package ledis provide session Provider -package ledis - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/adapter/session" - beeLedis "github.com/beego/beego/v2/server/web/session/ledis" -) - -// SessionStore ledis session store -type SessionStore beeLedis.SessionStore - -// Set value in ledis session -func (ls *SessionStore) Set(key, value interface{}) error { - return (*beeLedis.SessionStore)(ls).Set(context.Background(), key, value) -} - -// Get value in ledis session -func (ls *SessionStore) Get(key interface{}) interface{} { - return (*beeLedis.SessionStore)(ls).Get(context.Background(), key) -} - -// Delete value in ledis session -func (ls *SessionStore) Delete(key interface{}) error { - return (*beeLedis.SessionStore)(ls).Delete(context.Background(), key) -} - -// Flush clear all values in ledis session -func (ls *SessionStore) Flush() error { - return (*beeLedis.SessionStore)(ls).Flush(context.Background()) -} - -// SessionID get ledis session id -func (ls *SessionStore) SessionID() string { - return (*beeLedis.SessionStore)(ls).SessionID(context.Background()) -} - -// SessionRelease save session values to ledis -func (ls *SessionStore) SessionRelease(w http.ResponseWriter) { - (*beeLedis.SessionStore)(ls).SessionRelease(context.Background(), w) -} - -// Provider ledis session provider -type Provider beeLedis.Provider - -// SessionInit init ledis session -// savepath like ledis server saveDataPath,pool size -// e.g. 127.0.0.1:6379,100,astaxie -func (lp *Provider) SessionInit(maxlifetime int64, savePath string) error { - return (*beeLedis.Provider)(lp).SessionInit(context.Background(), maxlifetime, savePath) -} - -// SessionRead read ledis session by sid -func (lp *Provider) SessionRead(sid string) (session.Store, error) { - s, err := (*beeLedis.Provider)(lp).SessionRead(context.Background(), sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionExist check ledis session exist by sid -func (lp *Provider) SessionExist(sid string) bool { - res, _ := (*beeLedis.Provider)(lp).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate generate new sid for ledis session -func (lp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { - s, err := (*beeLedis.Provider)(lp).SessionRegenerate(context.Background(), oldsid, sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionDestroy delete ledis session by id -func (lp *Provider) SessionDestroy(sid string) error { - return (*beeLedis.Provider)(lp).SessionDestroy(context.Background(), sid) -} - -// SessionGC Impelment method, no used. -func (lp *Provider) SessionGC() { - (*beeLedis.Provider)(lp).SessionGC(context.Background()) -} - -// SessionAll return all active session -func (lp *Provider) SessionAll() int { - return (*beeLedis.Provider)(lp).SessionAll(context.Background()) -} diff --git a/adapter/session/memcache/sess_memcache.go b/adapter/session/memcache/sess_memcache.go deleted file mode 100644 index 4ca779f7..00000000 --- a/adapter/session/memcache/sess_memcache.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package memcache for session provider -// -// depend on github.com/bradfitz/gomemcache/memcache -// -// go install github.com/bradfitz/gomemcache/memcache -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/server/web/session/memcache" -// "github.com/beego/beego/v2/server/web/session" -// ) -// -// func init() { -// globalSessions, _ = session.NewManager("memcache", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:11211"}``) -// go globalSessions.GC() -// } -// -package memcache - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/adapter/session" - beemem "github.com/beego/beego/v2/server/web/session/memcache" -) - -// SessionStore memcache session store -type SessionStore beemem.SessionStore - -// Set value in memcache session -func (rs *SessionStore) Set(key, value interface{}) error { - return (*beemem.SessionStore)(rs).Set(context.Background(), key, value) -} - -// Get value in memcache session -func (rs *SessionStore) Get(key interface{}) interface{} { - return (*beemem.SessionStore)(rs).Get(context.Background(), key) -} - -// Delete value in memcache session -func (rs *SessionStore) Delete(key interface{}) error { - return (*beemem.SessionStore)(rs).Delete(context.Background(), key) -} - -// Flush clear all values in memcache session -func (rs *SessionStore) Flush() error { - return (*beemem.SessionStore)(rs).Flush(context.Background()) -} - -// SessionID get memcache session id -func (rs *SessionStore) SessionID() string { - return (*beemem.SessionStore)(rs).SessionID(context.Background()) -} - -// SessionRelease save session values to memcache -func (rs *SessionStore) SessionRelease(w http.ResponseWriter) { - (*beemem.SessionStore)(rs).SessionRelease(context.Background(), w) -} - -// MemProvider memcache session provider -type MemProvider beemem.MemProvider - -// SessionInit init memcache session -// savepath like -// e.g. 127.0.0.1:9090 -func (rp *MemProvider) SessionInit(maxlifetime int64, savePath string) error { - return (*beemem.MemProvider)(rp).SessionInit(context.Background(), maxlifetime, savePath) -} - -// SessionRead read memcache session by sid -func (rp *MemProvider) SessionRead(sid string) (session.Store, error) { - s, err := (*beemem.MemProvider)(rp).SessionRead(context.Background(), sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionExist check memcache session exist by sid -func (rp *MemProvider) SessionExist(sid string) bool { - res, _ := (*beemem.MemProvider)(rp).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate generate new sid for memcache session -func (rp *MemProvider) SessionRegenerate(oldsid, sid string) (session.Store, error) { - s, err := (*beemem.MemProvider)(rp).SessionRegenerate(context.Background(), oldsid, sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionDestroy delete memcache session by id -func (rp *MemProvider) SessionDestroy(sid string) error { - return (*beemem.MemProvider)(rp).SessionDestroy(context.Background(), sid) -} - -// SessionGC Impelment method, no used. -func (rp *MemProvider) SessionGC() { - (*beemem.MemProvider)(rp).SessionGC(context.Background()) -} - -// SessionAll return all activeSession -func (rp *MemProvider) SessionAll() int { - return (*beemem.MemProvider)(rp).SessionAll(context.Background()) -} diff --git a/adapter/session/mysql/sess_mysql.go b/adapter/session/mysql/sess_mysql.go deleted file mode 100644 index eb2bd090..00000000 --- a/adapter/session/mysql/sess_mysql.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package mysql for session provider -// -// depends on github.com/go-sql-driver/mysql: -// -// go install github.com/go-sql-driver/mysql -// -// mysql session support need create table as sql: -// CREATE TABLE `session` ( -// `session_key` char(64) NOT NULL, -// `session_data` blob, -// `session_expiry` int(11) unsigned NOT NULL, -// PRIMARY KEY (`session_key`) -// ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/server/web/session/mysql" -// "github.com/beego/beego/v2/server/web/session" -// ) -// -// func init() { -// globalSessions, _ = session.NewManager("mysql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]"}``) -// go globalSessions.GC() -// } -// -package mysql - -import ( - "context" - "net/http" - - _ "github.com/go-sql-driver/mysql" - - "github.com/beego/beego/v2/adapter/session" - "github.com/beego/beego/v2/server/web/session/mysql" -) - -var ( - // TableName store the session in MySQL - TableName = mysql.TableName - mysqlpder = &Provider{} -) - -// SessionStore mysql session store -type SessionStore mysql.SessionStore - -// Set value in mysql session. -// it is temp value in map. -func (st *SessionStore) Set(key, value interface{}) error { - return (*mysql.SessionStore)(st).Set(context.Background(), key, value) -} - -// Get value from mysql session -func (st *SessionStore) Get(key interface{}) interface{} { - return (*mysql.SessionStore)(st).Get(context.Background(), key) -} - -// Delete value in mysql session -func (st *SessionStore) Delete(key interface{}) error { - return (*mysql.SessionStore)(st).Delete(context.Background(), key) -} - -// Flush clear all values in mysql session -func (st *SessionStore) Flush() error { - return (*mysql.SessionStore)(st).Flush(context.Background()) -} - -// SessionID get session id of this mysql session store -func (st *SessionStore) SessionID() string { - return (*mysql.SessionStore)(st).SessionID(context.Background()) -} - -// SessionRelease save mysql session values to database. -// must call this method to save values to database. -func (st *SessionStore) SessionRelease(w http.ResponseWriter) { - (*mysql.SessionStore)(st).SessionRelease(context.Background(), w) -} - -// Provider mysql session provider -type Provider mysql.Provider - -// SessionInit init mysql session. -// savepath is the connection string of mysql. -func (mp *Provider) SessionInit(maxlifetime int64, savePath string) error { - return (*mysql.Provider)(mp).SessionInit(context.Background(), maxlifetime, savePath) -} - -// SessionRead get mysql session by sid -func (mp *Provider) SessionRead(sid string) (session.Store, error) { - s, err := (*mysql.Provider)(mp).SessionRead(context.Background(), sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionExist check mysql session exist -func (mp *Provider) SessionExist(sid string) bool { - res, _ := (*mysql.Provider)(mp).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate generate new sid for mysql session -func (mp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { - s, err := (*mysql.Provider)(mp).SessionRegenerate(context.Background(), oldsid, sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionDestroy delete mysql session by sid -func (mp *Provider) SessionDestroy(sid string) error { - return (*mysql.Provider)(mp).SessionDestroy(context.Background(), sid) -} - -// SessionGC delete expired values in mysql session -func (mp *Provider) SessionGC() { - (*mysql.Provider)(mp).SessionGC(context.Background()) -} - -// SessionAll count values in mysql session -func (mp *Provider) SessionAll() int { - return (*mysql.Provider)(mp).SessionAll(context.Background()) -} diff --git a/adapter/session/postgres/sess_postgresql.go b/adapter/session/postgres/sess_postgresql.go deleted file mode 100644 index b50e3c59..00000000 --- a/adapter/session/postgres/sess_postgresql.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package postgres for session provider -// -// depends on github.com/lib/pq: -// -// go install github.com/lib/pq -// -// -// needs this table in your database: -// -// CREATE TABLE session ( -// session_key char(64) NOT NULL, -// session_data bytea, -// session_expiry timestamp NOT NULL, -// CONSTRAINT session_key PRIMARY KEY(session_key) -// ); -// -// will be activated with these settings in app.conf: -// -// SessionOn = true -// SessionProvider = postgresql -// SessionSavePath = "user=a password=b dbname=c sslmode=disable" -// SessionName = session -// -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/server/web/session/postgresql" -// "github.com/beego/beego/v2/server/web/session" -// ) -// -// func init() { -// globalSessions, _ = session.NewManager("postgresql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"user=pqgotest dbname=pqgotest sslmode=verify-full"}``) -// go globalSessions.GC() -// } -// -package postgres - -import ( - "context" - "net/http" - - _ "github.com/lib/pq" - - "github.com/beego/beego/v2/adapter/session" - "github.com/beego/beego/v2/server/web/session/postgres" -) - -// SessionStore postgresql session store -type SessionStore postgres.SessionStore - -// Set value in postgresql session. -// it is temp value in map. -func (st *SessionStore) Set(key, value interface{}) error { - return (*postgres.SessionStore)(st).Set(context.Background(), key, value) -} - -// Get value from postgresql session -func (st *SessionStore) Get(key interface{}) interface{} { - return (*postgres.SessionStore)(st).Get(context.Background(), key) -} - -// Delete value in postgresql session -func (st *SessionStore) Delete(key interface{}) error { - return (*postgres.SessionStore)(st).Delete(context.Background(), key) -} - -// Flush clear all values in postgresql session -func (st *SessionStore) Flush() error { - return (*postgres.SessionStore)(st).Flush(context.Background()) -} - -// SessionID get session id of this postgresql session store -func (st *SessionStore) SessionID() string { - return (*postgres.SessionStore)(st).SessionID(context.Background()) -} - -// SessionRelease save postgresql session values to database. -// must call this method to save values to database. -func (st *SessionStore) SessionRelease(w http.ResponseWriter) { - (*postgres.SessionStore)(st).SessionRelease(context.Background(), w) -} - -// Provider postgresql session provider -type Provider postgres.Provider - -// SessionInit init postgresql session. -// savepath is the connection string of postgresql. -func (mp *Provider) SessionInit(maxlifetime int64, savePath string) error { - return (*postgres.Provider)(mp).SessionInit(context.Background(), maxlifetime, savePath) -} - -// SessionRead get postgresql session by sid -func (mp *Provider) SessionRead(sid string) (session.Store, error) { - s, err := (*postgres.Provider)(mp).SessionRead(context.Background(), sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionExist check postgresql session exist -func (mp *Provider) SessionExist(sid string) bool { - res, _ := (*postgres.Provider)(mp).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate generate new sid for postgresql session -func (mp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { - s, err := (*postgres.Provider)(mp).SessionRegenerate(context.Background(), oldsid, sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionDestroy delete postgresql session by sid -func (mp *Provider) SessionDestroy(sid string) error { - return (*postgres.Provider)(mp).SessionDestroy(context.Background(), sid) -} - -// SessionGC delete expired values in postgresql session -func (mp *Provider) SessionGC() { - (*postgres.Provider)(mp).SessionGC(context.Background()) -} - -// SessionAll count values in postgresql session -func (mp *Provider) SessionAll() int { - return (*postgres.Provider)(mp).SessionAll(context.Background()) -} diff --git a/adapter/session/provider_adapter.go b/adapter/session/provider_adapter.go deleted file mode 100644 index 3e62aa63..00000000 --- a/adapter/session/provider_adapter.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2020 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session - -import ( - "context" - - "github.com/beego/beego/v2/server/web/session" -) - -type oldToNewProviderAdapter struct { - delegate Provider -} - -func (o *oldToNewProviderAdapter) SessionInit(ctx context.Context, gclifetime int64, config string) error { - return o.delegate.SessionInit(gclifetime, config) -} - -func (o *oldToNewProviderAdapter) SessionRead(ctx context.Context, sid string) (session.Store, error) { - store, err := o.delegate.SessionRead(sid) - return &oldToNewStoreAdapter{ - delegate: store, - }, err -} - -func (o *oldToNewProviderAdapter) SessionExist(ctx context.Context, sid string) (bool, error) { - return o.delegate.SessionExist(sid), nil -} - -func (o *oldToNewProviderAdapter) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) { - s, err := o.delegate.SessionRegenerate(oldsid, sid) - return &oldToNewStoreAdapter{ - delegate: s, - }, err -} - -func (o *oldToNewProviderAdapter) SessionDestroy(ctx context.Context, sid string) error { - return o.delegate.SessionDestroy(sid) -} - -func (o *oldToNewProviderAdapter) SessionAll(ctx context.Context) int { - return o.delegate.SessionAll() -} - -func (o *oldToNewProviderAdapter) SessionGC(ctx context.Context) { - o.delegate.SessionGC() -} - -type newToOldProviderAdapter struct { - delegate session.Provider -} - -func (n *newToOldProviderAdapter) SessionInit(gclifetime int64, config string) error { - return n.delegate.SessionInit(context.Background(), gclifetime, config) -} - -func (n *newToOldProviderAdapter) SessionRead(sid string) (Store, error) { - s, err := n.delegate.SessionRead(context.Background(), sid) - if adt, ok := s.(*oldToNewStoreAdapter); err == nil && ok { - return adt.delegate, err - } - return &NewToOldStoreAdapter{ - delegate: s, - }, err -} - -func (n *newToOldProviderAdapter) SessionExist(sid string) bool { - res, _ := n.delegate.SessionExist(context.Background(), sid) - return res -} - -func (n *newToOldProviderAdapter) SessionRegenerate(oldsid, sid string) (Store, error) { - s, err := n.delegate.SessionRegenerate(context.Background(), oldsid, sid) - if adt, ok := s.(*oldToNewStoreAdapter); err == nil && ok { - return adt.delegate, err - } - return &NewToOldStoreAdapter{ - delegate: s, - }, err -} - -func (n *newToOldProviderAdapter) SessionDestroy(sid string) error { - return n.delegate.SessionDestroy(context.Background(), sid) -} - -func (n *newToOldProviderAdapter) SessionAll() int { - return n.delegate.SessionAll(context.Background()) -} - -func (n *newToOldProviderAdapter) SessionGC() { - n.delegate.SessionGC(context.Background()) -} diff --git a/adapter/session/redis/sess_redis.go b/adapter/session/redis/sess_redis.go deleted file mode 100644 index 7d3287ff..00000000 --- a/adapter/session/redis/sess_redis.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package redis for session provider -// -// depend on github.com/gomodule/redigo/redis -// -// go install github.com/gomodule/redigo/redis -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/server/web/session/redis" -// "github.com/beego/beego/v2/server/web/session" -// ) -// -// func init() { -// globalSessions, _ = session.NewManager("redis", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070"}``) -// go globalSessions.GC() -// } -// -package redis - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/adapter/session" - beeRedis "github.com/beego/beego/v2/server/web/session/redis" -) - -// MaxPoolSize redis max pool size -var MaxPoolSize = beeRedis.MaxPoolSize - -// SessionStore redis session store -type SessionStore beeRedis.SessionStore - -// Set value in redis session -func (rs *SessionStore) Set(key, value interface{}) error { - return (*beeRedis.SessionStore)(rs).Set(context.Background(), key, value) -} - -// Get value in redis session -func (rs *SessionStore) Get(key interface{}) interface{} { - return (*beeRedis.SessionStore)(rs).Get(context.Background(), key) -} - -// Delete value in redis session -func (rs *SessionStore) Delete(key interface{}) error { - return (*beeRedis.SessionStore)(rs).Delete(context.Background(), key) -} - -// Flush clear all values in redis session -func (rs *SessionStore) Flush() error { - return (*beeRedis.SessionStore)(rs).Flush(context.Background()) -} - -// SessionID get redis session id -func (rs *SessionStore) SessionID() string { - return (*beeRedis.SessionStore)(rs).SessionID(context.Background()) -} - -// SessionRelease save session values to redis -func (rs *SessionStore) SessionRelease(w http.ResponseWriter) { - (*beeRedis.SessionStore)(rs).SessionRelease(context.Background(), w) -} - -// Provider redis session provider -type Provider beeRedis.Provider - -// SessionInit init redis session -// savepath like redis server addr,pool size,password,dbnum,IdleTimeout second -// e.g. 127.0.0.1:6379,100,astaxie,0,30 -func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error { - return (*beeRedis.Provider)(rp).SessionInit(context.Background(), maxlifetime, savePath) -} - -// SessionRead read redis session by sid -func (rp *Provider) SessionRead(sid string) (session.Store, error) { - s, err := (*beeRedis.Provider)(rp).SessionRead(context.Background(), sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionExist check redis session exist by sid -func (rp *Provider) SessionExist(sid string) bool { - res, _ := (*beeRedis.Provider)(rp).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate generate new sid for redis session -func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { - s, err := (*beeRedis.Provider)(rp).SessionRegenerate(context.Background(), oldsid, sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionDestroy delete redis session by id -func (rp *Provider) SessionDestroy(sid string) error { - return (*beeRedis.Provider)(rp).SessionDestroy(context.Background(), sid) -} - -// SessionGC Impelment method, no used. -func (rp *Provider) SessionGC() { - (*beeRedis.Provider)(rp).SessionGC(context.Background()) -} - -// SessionAll return all activeSession -func (rp *Provider) SessionAll() int { - return (*beeRedis.Provider)(rp).SessionAll(context.Background()) -} diff --git a/adapter/session/redis_cluster/redis_cluster.go b/adapter/session/redis_cluster/redis_cluster.go deleted file mode 100644 index 4b9c09b4..00000000 --- a/adapter/session/redis_cluster/redis_cluster.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package redis for session provider -// -// depend on github.com/go-redis/redis -// -// go install github.com/go-redis/redis -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/server/web/session/redis_cluster" -// "github.com/beego/beego/v2/server/web/session" -// ) -// -// func init() { -// globalSessions, _ = session.NewManager("redis_cluster", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070;127.0.0.1:7071"}``) -// go globalSessions.GC() -// } -// -package redis_cluster - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/adapter/session" - cluster "github.com/beego/beego/v2/server/web/session/redis_cluster" -) - -// MaxPoolSize redis_cluster max pool size -var MaxPoolSize = cluster.MaxPoolSize - -// SessionStore redis_cluster session store -type SessionStore cluster.SessionStore - -// Set value in redis_cluster session -func (rs *SessionStore) Set(key, value interface{}) error { - return (*cluster.SessionStore)(rs).Set(context.Background(), key, value) -} - -// Get value in redis_cluster session -func (rs *SessionStore) Get(key interface{}) interface{} { - return (*cluster.SessionStore)(rs).Get(context.Background(), key) -} - -// Delete value in redis_cluster session -func (rs *SessionStore) Delete(key interface{}) error { - return (*cluster.SessionStore)(rs).Delete(context.Background(), key) -} - -// Flush clear all values in redis_cluster session -func (rs *SessionStore) Flush() error { - return (*cluster.SessionStore)(rs).Flush(context.Background()) -} - -// SessionID get redis_cluster session id -func (rs *SessionStore) SessionID() string { - return (*cluster.SessionStore)(rs).SessionID(context.Background()) -} - -// SessionRelease save session values to redis_cluster -func (rs *SessionStore) SessionRelease(w http.ResponseWriter) { - (*cluster.SessionStore)(rs).SessionRelease(context.Background(), w) -} - -// Provider redis_cluster session provider -type Provider cluster.Provider - -// SessionInit init redis_cluster session -// savepath like redis server addr,pool size,password,dbnum -// e.g. 127.0.0.1:6379;127.0.0.1:6380,100,test,0 -func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error { - return (*cluster.Provider)(rp).SessionInit(context.Background(), maxlifetime, savePath) -} - -// SessionRead read redis_cluster session by sid -func (rp *Provider) SessionRead(sid string) (session.Store, error) { - s, err := (*cluster.Provider)(rp).SessionRead(context.Background(), sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionExist check redis_cluster session exist by sid -func (rp *Provider) SessionExist(sid string) bool { - res, _ := (*cluster.Provider)(rp).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate generate new sid for redis_cluster session -func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { - s, err := (*cluster.Provider)(rp).SessionRegenerate(context.Background(), oldsid, sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionDestroy delete redis session by id -func (rp *Provider) SessionDestroy(sid string) error { - return (*cluster.Provider)(rp).SessionDestroy(context.Background(), sid) -} - -// SessionGC Impelment method, no used. -func (rp *Provider) SessionGC() { - (*cluster.Provider)(rp).SessionGC(context.Background()) -} - -// SessionAll return all activeSession -func (rp *Provider) SessionAll() int { - return (*cluster.Provider)(rp).SessionAll(context.Background()) -} diff --git a/adapter/session/redis_sentinel/sess_redis_sentinel.go b/adapter/session/redis_sentinel/sess_redis_sentinel.go deleted file mode 100644 index 633fb5fa..00000000 --- a/adapter/session/redis_sentinel/sess_redis_sentinel.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package redis for session provider -// -// depend on github.com/go-redis/redis -// -// go install github.com/go-redis/redis -// -// Usage: -// import( -// _ "github.com/beego/beego/v2/server/web/session/redis_sentinel" -// "github.com/beego/beego/v2/server/web/session" -// ) -// -// func init() { -// globalSessions, _ = session.NewManager("redis_sentinel", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:26379;127.0.0.2:26379"}``) -// go globalSessions.GC() -// } -// -// more detail about params: please check the notes on the function SessionInit in this package -package redis_sentinel - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/adapter/session" - sentinel "github.com/beego/beego/v2/server/web/session/redis_sentinel" -) - -// DefaultPoolSize redis_sentinel default pool size -var DefaultPoolSize = sentinel.DefaultPoolSize - -// SessionStore redis_sentinel session store -type SessionStore sentinel.SessionStore - -// Set value in redis_sentinel session -func (rs *SessionStore) Set(key, value interface{}) error { - return (*sentinel.SessionStore)(rs).Set(context.Background(), key, value) -} - -// Get value in redis_sentinel session -func (rs *SessionStore) Get(key interface{}) interface{} { - return (*sentinel.SessionStore)(rs).Get(context.Background(), key) -} - -// Delete value in redis_sentinel session -func (rs *SessionStore) Delete(key interface{}) error { - return (*sentinel.SessionStore)(rs).Delete(context.Background(), key) -} - -// Flush clear all values in redis_sentinel session -func (rs *SessionStore) Flush() error { - return (*sentinel.SessionStore)(rs).Flush(context.Background()) -} - -// SessionID get redis_sentinel session id -func (rs *SessionStore) SessionID() string { - return (*sentinel.SessionStore)(rs).SessionID(context.Background()) -} - -// SessionRelease save session values to redis_sentinel -func (rs *SessionStore) SessionRelease(w http.ResponseWriter) { - (*sentinel.SessionStore)(rs).SessionRelease(context.Background(), w) -} - -// Provider redis_sentinel session provider -type Provider sentinel.Provider - -// SessionInit init redis_sentinel session -// savepath like redis sentinel addr,pool size,password,dbnum,masterName -// e.g. 127.0.0.1:26379;127.0.0.2:26379,100,1qaz2wsx,0,mymaster -func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error { - return (*sentinel.Provider)(rp).SessionInit(context.Background(), maxlifetime, savePath) -} - -// SessionRead read redis_sentinel session by sid -func (rp *Provider) SessionRead(sid string) (session.Store, error) { - s, err := (*sentinel.Provider)(rp).SessionRead(context.Background(), sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionExist check redis_sentinel session exist by sid -func (rp *Provider) SessionExist(sid string) bool { - res, _ := (*sentinel.Provider)(rp).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate generate new sid for redis_sentinel session -func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { - s, err := (*sentinel.Provider)(rp).SessionRegenerate(context.Background(), oldsid, sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionDestroy delete redis session by id -func (rp *Provider) SessionDestroy(sid string) error { - return (*sentinel.Provider)(rp).SessionDestroy(context.Background(), sid) -} - -// SessionGC Impelment method, no used. -func (rp *Provider) SessionGC() { - (*sentinel.Provider)(rp).SessionGC(context.Background()) -} - -// SessionAll return all activeSession -func (rp *Provider) SessionAll() int { - return (*sentinel.Provider)(rp).SessionAll(context.Background()) -} diff --git a/adapter/session/redis_sentinel/sess_redis_sentinel_test.go b/adapter/session/redis_sentinel/sess_redis_sentinel_test.go deleted file mode 100644 index 2d381af6..00000000 --- a/adapter/session/redis_sentinel/sess_redis_sentinel_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package redis_sentinel - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/beego/beego/v2/adapter/session" -) - -func TestRedisSentinel(t *testing.T) { - sessionConfig := &session.ManagerConfig{ - CookieName: "gosessionid", - EnableSetCookie: true, - Gclifetime: 3600, - Maxlifetime: 3600, - Secure: false, - CookieLifeTime: 3600, - ProviderConfig: "127.0.0.1:6379,100,,0,master", - } - globalSessions, e := session.NewManager("redis_sentinel", sessionConfig) - - if e != nil { - t.Log(e) - return - } - - go globalSessions.GC() - - r, _ := http.NewRequest("GET", "/", nil) - w := httptest.NewRecorder() - - sess, err := globalSessions.SessionStart(w, r) - assert.Nil(t, err) - defer sess.SessionRelease(w) - - // SET AND GET - err = sess.Set("username", "astaxie") - assert.Nil(t, err) - username := sess.Get("username") - assert.Equal(t, "astaxie", username) - - // DELETE - err = sess.Delete("username") - assert.Nil(t, err) - - username = sess.Get("username") - assert.Nil(t, username) - - // FLUSH - err = sess.Set("username", "astaxie") - assert.Nil(t, err) - - err = sess.Set("password", "1qaz2wsx") - assert.Nil(t, err) - - username = sess.Get("username") - assert.Equal(t, "astaxie", username) - - password := sess.Get("password") - assert.Equal(t, "1qaz2wsx", password) - - err = sess.Flush() - assert.Nil(t, err) - - username = sess.Get("username") - assert.Nil(t, username) - - password = sess.Get("password") - assert.Nil(t, password) - - sess.SessionRelease(w) -} diff --git a/adapter/session/sess_cookie.go b/adapter/session/sess_cookie.go deleted file mode 100644 index ef3b6799..00000000 --- a/adapter/session/sess_cookie.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/server/web/session" -) - -// CookieSessionStore Cookie SessionStore -type CookieSessionStore session.CookieSessionStore - -// Set value to cookie session. -// the value are encoded as gob with hash block string. -func (st *CookieSessionStore) Set(key, value interface{}) error { - return (*session.CookieSessionStore)(st).Set(context.Background(), key, value) -} - -// Get value from cookie session -func (st *CookieSessionStore) Get(key interface{}) interface{} { - return (*session.CookieSessionStore)(st).Get(context.Background(), key) -} - -// Delete value in cookie session -func (st *CookieSessionStore) Delete(key interface{}) error { - return (*session.CookieSessionStore)(st).Delete(context.Background(), key) -} - -// Flush Clean all values in cookie session -func (st *CookieSessionStore) Flush() error { - return (*session.CookieSessionStore)(st).Flush(context.Background()) -} - -// SessionID Return id of this cookie session -func (st *CookieSessionStore) SessionID() string { - return (*session.CookieSessionStore)(st).SessionID(context.Background()) -} - -// SessionRelease Write cookie session to http response cookie -func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) { - (*session.CookieSessionStore)(st).SessionRelease(context.Background(), w) -} - -// CookieProvider Cookie session provider -type CookieProvider session.CookieProvider - -// SessionInit Init cookie session provider with max lifetime and config json. -// maxlifetime is ignored. -// json config: -// securityKey - hash string -// blockKey - gob encode hash string. it's saved as aes crypto. -// securityName - recognized name in encoded cookie string -// cookieName - cookie name -// maxage - cookie max life time. -func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error { - return (*session.CookieProvider)(pder).SessionInit(context.Background(), maxlifetime, config) -} - -// SessionRead Get SessionStore in cooke. -// decode cooke string to map and put into SessionStore with sid. -func (pder *CookieProvider) SessionRead(sid string) (Store, error) { - s, err := (*session.CookieProvider)(pder).SessionRead(context.Background(), sid) - return &NewToOldStoreAdapter{ - delegate: s, - }, err -} - -// SessionExist Cookie session is always existed -func (pder *CookieProvider) SessionExist(sid string) bool { - res, _ := (*session.CookieProvider)(pder).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate Implement method, no used. -func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (Store, error) { - s, err := (*session.CookieProvider)(pder).SessionRegenerate(context.Background(), oldsid, sid) - return &NewToOldStoreAdapter{ - delegate: s, - }, err -} - -// SessionDestroy Implement method, no used. -func (pder *CookieProvider) SessionDestroy(sid string) error { - return (*session.CookieProvider)(pder).SessionDestroy(context.Background(), sid) -} - -// SessionGC Implement method, no used. -func (pder *CookieProvider) SessionGC() { - (*session.CookieProvider)(pder).SessionGC(context.Background()) -} - -// SessionAll Implement method, return 0. -func (pder *CookieProvider) SessionAll() int { - return (*session.CookieProvider)(pder).SessionAll(context.Background()) -} - -// SessionUpdate Implement method, no used. -func (pder *CookieProvider) SessionUpdate(sid string) error { - return (*session.CookieProvider)(pder).SessionUpdate(context.Background(), sid) -} diff --git a/adapter/session/sess_cookie_test.go b/adapter/session/sess_cookie_test.go deleted file mode 100644 index 61937f56..00000000 --- a/adapter/session/sess_cookie_test.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "strings" - "testing" -) - -const setCookieKey = "Set-Cookie" - -func TestCookie(t *testing.T) { - config := `{"cookieName":"gosessionid","enableSetCookie":false,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}` - conf := new(ManagerConfig) - if err := json.Unmarshal([]byte(config), conf); err != nil { - t.Fatal("json decode error", err) - } - globalSessions, err := NewManager("cookie", conf) - if err != nil { - t.Fatal("init cookie session err", err) - } - r, _ := http.NewRequest("GET", "/", nil) - w := httptest.NewRecorder() - sess, err := globalSessions.SessionStart(w, r) - if err != nil { - t.Fatal("set error,", err) - } - err = sess.Set("username", "astaxie") - if err != nil { - t.Fatal("set error,", err) - } - if username := sess.Get("username"); username != "astaxie" { - t.Fatal("get username error") - } - sess.SessionRelease(w) - - if cookiestr := w.Header().Get(setCookieKey); cookiestr == "" { - t.Fatal("setcookie error") - } else { - parts := strings.Split(strings.TrimSpace(cookiestr), ";") - for k, v := range parts { - nameval := strings.Split(v, "=") - if k == 0 && nameval[0] != "gosessionid" { - t.Fatal("error") - } - } - } -} - -func TestDestorySessionCookie(t *testing.T) { - config := `{"cookieName":"gosessionid","enableSetCookie":true,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}` - conf := new(ManagerConfig) - if err := json.Unmarshal([]byte(config), conf); err != nil { - t.Fatal("json decode error", err) - } - globalSessions, err := NewManager("cookie", conf) - if err != nil { - t.Fatal("init cookie session err", err) - } - - r, _ := http.NewRequest("GET", "/", nil) - w := httptest.NewRecorder() - session, err := globalSessions.SessionStart(w, r) - if err != nil { - t.Fatal("session start err,", err) - } - - // request again ,will get same sesssion id . - r1, _ := http.NewRequest("GET", "/", nil) - r1.Header.Set("Cookie", w.Header().Get(setCookieKey)) - w = httptest.NewRecorder() - newSession, err := globalSessions.SessionStart(w, r1) - if err != nil { - t.Fatal("session start err,", err) - } - if newSession.SessionID() != session.SessionID() { - t.Fatal("get cookie session id is not the same again.") - } - - // After destroy session , will get a new session id . - globalSessions.SessionDestroy(w, r1) - r2, _ := http.NewRequest("GET", "/", nil) - r2.Header.Set("Cookie", w.Header().Get(setCookieKey)) - - w = httptest.NewRecorder() - newSession, err = globalSessions.SessionStart(w, r2) - if err != nil { - t.Fatal("session start error") - } - if newSession.SessionID() == session.SessionID() { - t.Fatal("after destroy session and reqeust again ,get cookie session id is same.") - } -} diff --git a/adapter/session/sess_file.go b/adapter/session/sess_file.go deleted file mode 100644 index c201cf74..00000000 --- a/adapter/session/sess_file.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/server/web/session" -) - -// FileSessionStore File session store -type FileSessionStore session.FileSessionStore - -// Set value to file session -func (fs *FileSessionStore) Set(key, value interface{}) error { - return (*session.FileSessionStore)(fs).Set(context.Background(), key, value) -} - -// Get value from file session -func (fs *FileSessionStore) Get(key interface{}) interface{} { - return (*session.FileSessionStore)(fs).Get(context.Background(), key) -} - -// Delete value in file session by given key -func (fs *FileSessionStore) Delete(key interface{}) error { - return (*session.FileSessionStore)(fs).Delete(context.Background(), key) -} - -// Flush Clean all values in file session -func (fs *FileSessionStore) Flush() error { - return (*session.FileSessionStore)(fs).Flush(context.Background()) -} - -// SessionID Get file session store id -func (fs *FileSessionStore) SessionID() string { - return (*session.FileSessionStore)(fs).SessionID(context.Background()) -} - -// SessionRelease Write file session to local file with Gob string -func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) { - (*session.FileSessionStore)(fs).SessionRelease(context.Background(), w) -} - -// FileProvider File session provider -type FileProvider session.FileProvider - -// SessionInit Init file session provider. -// savePath sets the session files path. -func (fp *FileProvider) SessionInit(maxlifetime int64, savePath string) error { - return (*session.FileProvider)(fp).SessionInit(context.Background(), maxlifetime, savePath) -} - -// SessionRead Read file session by sid. -// if file is not exist, create it. -// the file path is generated from sid string. -func (fp *FileProvider) SessionRead(sid string) (Store, error) { - s, err := (*session.FileProvider)(fp).SessionRead(context.Background(), sid) - return &NewToOldStoreAdapter{ - delegate: s, - }, err -} - -// SessionExist Check file session exist. -// it checks the file named from sid exist or not. -func (fp *FileProvider) SessionExist(sid string) bool { - res, _ := (*session.FileProvider)(fp).SessionExist(context.Background(), sid) - return res -} - -// SessionDestroy Remove all files in this save path -func (fp *FileProvider) SessionDestroy(sid string) error { - return (*session.FileProvider)(fp).SessionDestroy(context.Background(), sid) -} - -// SessionGC Recycle files in save path -func (fp *FileProvider) SessionGC() { - (*session.FileProvider)(fp).SessionGC(context.Background()) -} - -// SessionAll Get active file session number. -// it walks save path to count files. -func (fp *FileProvider) SessionAll() int { - return (*session.FileProvider)(fp).SessionAll(context.Background()) -} - -// SessionRegenerate Generate new sid for file session. -// it delete old file and create new file named from new sid. -func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (Store, error) { - s, err := (*session.FileProvider)(fp).SessionRegenerate(context.Background(), oldsid, sid) - return &NewToOldStoreAdapter{ - delegate: s, - }, err -} diff --git a/adapter/session/sess_file_test.go b/adapter/session/sess_file_test.go deleted file mode 100644 index a3e3d0b9..00000000 --- a/adapter/session/sess_file_test.go +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session - -import ( - "fmt" - "os" - "sync" - "testing" - "time" -) - -const ( - sid = "Session_id" - sidNew = "Session_id_new" - sessionPath = "./_session_runtime" -) - -var mutex sync.Mutex - -func TestFileProviderSessionExist(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - if fp.SessionExist(sid) { - t.Error() - } - - _, err := fp.SessionRead(sid) - if err != nil { - t.Error(err) - } - - if !fp.SessionExist(sid) { - t.Error() - } -} - -func TestFileProviderSessionExist2(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - if fp.SessionExist(sid) { - t.Error() - } - - if fp.SessionExist("") { - t.Error() - } - - if fp.SessionExist("1") { - t.Error() - } -} - -func TestFileProviderSessionRead(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - s, err := fp.SessionRead(sid) - if err != nil { - t.Error(err) - } - - _ = s.Set("sessionValue", 18975) - v := s.Get("sessionValue") - - if v.(int) != 18975 { - t.Error() - } -} - -func TestFileProviderSessionRead1(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - _, err := fp.SessionRead("") - if err == nil { - t.Error(err) - } - - _, err = fp.SessionRead("1") - if err == nil { - t.Error(err) - } -} - -func TestFileProviderSessionAll(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - sessionCount := 546 - - for i := 1; i <= sessionCount; i++ { - _, err := fp.SessionRead(fmt.Sprintf("%s_%d", sid, i)) - if err != nil { - t.Error(err) - } - } - - if fp.SessionAll() != sessionCount { - t.Error() - } -} - -func TestFileProviderSessionRegenerate(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - _, err := fp.SessionRead(sid) - if err != nil { - t.Error(err) - } - - if !fp.SessionExist(sid) { - t.Error() - } - - _, err = fp.SessionRegenerate(sid, sidNew) - if err != nil { - t.Error(err) - } - - if fp.SessionExist(sid) { - t.Error() - } - - if !fp.SessionExist(sidNew) { - t.Error() - } -} - -func TestFileProviderSessionDestroy(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - _, err := fp.SessionRead(sid) - if err != nil { - t.Error(err) - } - - if !fp.SessionExist(sid) { - t.Error() - } - - err = fp.SessionDestroy(sid) - if err != nil { - t.Error(err) - } - - if fp.SessionExist(sid) { - t.Error() - } -} - -func TestFileProviderSessionGC(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(1, sessionPath) - - sessionCount := 412 - - for i := 1; i <= sessionCount; i++ { - _, err := fp.SessionRead(fmt.Sprintf("%s_%d", sid, i)) - if err != nil { - t.Error(err) - } - } - - time.Sleep(2 * time.Second) - - fp.SessionGC() - if fp.SessionAll() != 0 { - t.Error() - } -} - -func TestFileSessionStoreSet(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - sessionCount := 100 - s, _ := fp.SessionRead(sid) - for i := 1; i <= sessionCount; i++ { - err := s.Set(i, i) - if err != nil { - t.Error(err) - } - } -} - -func TestFileSessionStoreGet(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - sessionCount := 100 - s, _ := fp.SessionRead(sid) - for i := 1; i <= sessionCount; i++ { - _ = s.Set(i, i) - - v := s.Get(i) - if v.(int) != i { - t.Error() - } - } -} - -func TestFileSessionStoreDelete(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - s, _ := fp.SessionRead(sid) - s.Set("1", 1) - - if s.Get("1") == nil { - t.Error() - } - - s.Delete("1") - - if s.Get("1") != nil { - t.Error() - } -} - -func TestFileSessionStoreFlush(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - sessionCount := 100 - s, _ := fp.SessionRead(sid) - for i := 1; i <= sessionCount; i++ { - _ = s.Set(i, i) - } - - _ = s.Flush() - - for i := 1; i <= sessionCount; i++ { - if s.Get(i) != nil { - t.Error() - } - } -} - -func TestFileSessionStoreSessionID(t *testing.T) { - mutex.Lock() - defer mutex.Unlock() - os.RemoveAll(sessionPath) - defer os.RemoveAll(sessionPath) - fp := &FileProvider{} - - _ = fp.SessionInit(180, sessionPath) - - sessionCount := 85 - - for i := 1; i <= sessionCount; i++ { - s, err := fp.SessionRead(fmt.Sprintf("%s_%d", sid, i)) - if err != nil { - t.Error(err) - } - if s.SessionID() != fmt.Sprintf("%s_%d", sid, i) { - t.Error(err) - } - } -} diff --git a/adapter/session/sess_mem.go b/adapter/session/sess_mem.go deleted file mode 100644 index 6a4e62c6..00000000 --- a/adapter/session/sess_mem.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/server/web/session" -) - -// MemSessionStore memory session store. -// it saved sessions in a map in memory. -type MemSessionStore session.MemSessionStore - -// Set value to memory session -func (st *MemSessionStore) Set(key, value interface{}) error { - return (*session.MemSessionStore)(st).Set(context.Background(), key, value) -} - -// Get value from memory session by key -func (st *MemSessionStore) Get(key interface{}) interface{} { - return (*session.MemSessionStore)(st).Get(context.Background(), key) -} - -// Delete in memory session by key -func (st *MemSessionStore) Delete(key interface{}) error { - return (*session.MemSessionStore)(st).Delete(context.Background(), key) -} - -// Flush clear all values in memory session -func (st *MemSessionStore) Flush() error { - return (*session.MemSessionStore)(st).Flush(context.Background()) -} - -// SessionID get this id of memory session store -func (st *MemSessionStore) SessionID() string { - return (*session.MemSessionStore)(st).SessionID(context.Background()) -} - -// SessionRelease Implement method, no used. -func (st *MemSessionStore) SessionRelease(w http.ResponseWriter) { - (*session.MemSessionStore)(st).SessionRelease(context.Background(), w) -} - -// MemProvider Implement the provider interface -type MemProvider session.MemProvider - -// SessionInit init memory session -func (pder *MemProvider) SessionInit(maxlifetime int64, savePath string) error { - return (*session.MemProvider)(pder).SessionInit(context.Background(), maxlifetime, savePath) -} - -// SessionRead get memory session store by sid -func (pder *MemProvider) SessionRead(sid string) (Store, error) { - s, err := (*session.MemProvider)(pder).SessionRead(context.Background(), sid) - return &NewToOldStoreAdapter{ - delegate: s, - }, err -} - -// SessionExist check session store exist in memory session by sid -func (pder *MemProvider) SessionExist(sid string) bool { - res, _ := (*session.MemProvider)(pder).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate generate new sid for session store in memory session -func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (Store, error) { - s, err := (*session.MemProvider)(pder).SessionRegenerate(context.Background(), oldsid, sid) - return &NewToOldStoreAdapter{ - delegate: s, - }, err -} - -// SessionDestroy delete session store in memory session by id -func (pder *MemProvider) SessionDestroy(sid string) error { - return (*session.MemProvider)(pder).SessionDestroy(context.Background(), sid) -} - -// SessionGC clean expired session stores in memory session -func (pder *MemProvider) SessionGC() { - (*session.MemProvider)(pder).SessionGC(context.Background()) -} - -// SessionAll get count number of memory session -func (pder *MemProvider) SessionAll() int { - return (*session.MemProvider)(pder).SessionAll(context.Background()) -} - -// SessionUpdate expand time of session store by id in memory session -func (pder *MemProvider) SessionUpdate(sid string) error { - return (*session.MemProvider)(pder).SessionUpdate(context.Background(), sid) -} diff --git a/adapter/session/sess_mem_test.go b/adapter/session/sess_mem_test.go deleted file mode 100644 index 2e8934b8..00000000 --- a/adapter/session/sess_mem_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "strings" - "testing" -) - -func TestMem(t *testing.T) { - config := `{"cookieName":"gosessionid","gclifetime":10, "enableSetCookie":true}` - conf := new(ManagerConfig) - if err := json.Unmarshal([]byte(config), conf); err != nil { - t.Fatal("json decode error", err) - } - globalSessions, _ := NewManager("memory", conf) - go globalSessions.GC() - r, _ := http.NewRequest("GET", "/", nil) - w := httptest.NewRecorder() - sess, err := globalSessions.SessionStart(w, r) - if err != nil { - t.Fatal("set error,", err) - } - defer sess.SessionRelease(w) - err = sess.Set("username", "astaxie") - if err != nil { - t.Fatal("set error,", err) - } - if username := sess.Get("username"); username != "astaxie" { - t.Fatal("get username error") - } - if cookiestr := w.Header().Get("Set-Cookie"); cookiestr == "" { - t.Fatal("setcookie error") - } else { - parts := strings.Split(strings.TrimSpace(cookiestr), ";") - for k, v := range parts { - nameval := strings.Split(v, "=") - if k == 0 && nameval[0] != "gosessionid" { - t.Fatal("error") - } - } - } -} diff --git a/adapter/session/sess_test.go b/adapter/session/sess_test.go deleted file mode 100644 index 2ecd2dd9..00000000 --- a/adapter/session/sess_test.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session - -import ( - "testing" -) - -func TestGob(t *testing.T) { - a := make(map[interface{}]interface{}) - a["username"] = "astaxie" - a[12] = 234 - a["user"] = User{"asta", "xie"} - b, err := EncodeGob(a) - if err != nil { - t.Error(err) - } - c, err := DecodeGob(b) - if err != nil { - t.Error(err) - } - if len(c) == 0 { - t.Error("decodeGob empty") - } - if c["username"] != "astaxie" { - t.Error("decode string error") - } - if c[12] != 234 { - t.Error("decode int error") - } - if c["user"].(User).Username != "asta" { - t.Error("decode struct error") - } -} - -type User struct { - Username string - NickName string -} diff --git a/adapter/session/sess_utils.go b/adapter/session/sess_utils.go deleted file mode 100644 index 2fe229d7..00000000 --- a/adapter/session/sess_utils.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session - -import ( - "github.com/beego/beego/v2/server/web/session" -) - -// EncodeGob encode the obj to gob -func EncodeGob(obj map[interface{}]interface{}) ([]byte, error) { - return session.EncodeGob(obj) -} - -// DecodeGob decode data to map -func DecodeGob(encoded []byte) (map[interface{}]interface{}, error) { - return session.DecodeGob(encoded) -} diff --git a/adapter/session/session.go b/adapter/session/session.go deleted file mode 100644 index 256bd601..00000000 --- a/adapter/session/session.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package session provider -// -// Usage: -// import( -// "github.com/beego/beego/v2/server/web/session" -// ) -// -// func init() { -// globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid", "enableSetCookie,omitempty": true, "gclifetime":3600, "maxLifetime": 3600, "secure": false, "cookieLifeTime": 3600, "providerConfig": ""}`) -// go globalSessions.GC() -// } -// -package session - -import ( - "io" - "net/http" - "os" - - "github.com/beego/beego/v2/server/web/session" -) - -// Store contains all data for one session process with specific id. -type Store interface { - Set(key, value interface{}) error // set session value - Get(key interface{}) interface{} // get session value - Delete(key interface{}) error // delete session value - SessionID() string // back current sessionID - SessionRelease(w http.ResponseWriter) // release the resource & save data to provider & return the data - Flush() error // delete all data -} - -// Provider contains global session methods and saved SessionStores. -// it can operate a SessionStore by its id. -type Provider interface { - SessionInit(gclifetime int64, config string) error - SessionRead(sid string) (Store, error) - SessionExist(sid string) bool - SessionRegenerate(oldsid, sid string) (Store, error) - SessionDestroy(sid string) error - SessionAll() int // get all active session - SessionGC() -} - -// SLogger a helpful variable to log information about session -var SLogger = NewSessionLog(os.Stderr) - -// Register makes a session provide available by the provided name. -// If Register is called twice with the same name or if driver is nil, -// it panics. -func Register(name string, provide Provider) { - session.Register(name, &oldToNewProviderAdapter{ - delegate: provide, - }) -} - -// GetProvider -func GetProvider(name string) (Provider, error) { - res, err := session.GetProvider(name) - if adt, ok := res.(*oldToNewProviderAdapter); err == nil && ok { - return adt.delegate, err - } - - return &newToOldProviderAdapter{ - delegate: res, - }, err -} - -// ManagerConfig define the session config -type ManagerConfig session.ManagerConfig - -// Manager contains Provider and its configuration. -type Manager session.Manager - -// NewManager Create new Manager with provider name and json config string. -// provider name: -// 1. cookie -// 2. file -// 3. memory -// 4. redis -// 5. mysql -// json config: -// 1. is https default false -// 2. hashfunc default sha1 -// 3. hashkey default beegosessionkey -// 4. maxage default is none -func NewManager(provideName string, cf *ManagerConfig) (*Manager, error) { - m, err := session.NewManager(provideName, (*session.ManagerConfig)(cf)) - return (*Manager)(m), err -} - -// GetProvider return current manager's provider -func (manager *Manager) GetProvider() Provider { - return &newToOldProviderAdapter{ - delegate: (*session.Manager)(manager).GetProvider(), - } -} - -// SessionStart generate or read the session id from http request. -// if session id exists, return SessionStore with this id. -func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (Store, error) { - s, err := (*session.Manager)(manager).SessionStart(w, r) - return &NewToOldStoreAdapter{ - delegate: s, - }, err -} - -// SessionDestroy Destroy session by its id in http request cookie. -func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) { - (*session.Manager)(manager).SessionDestroy(w, r) -} - -// GetSessionStore Get SessionStore by its id. -func (manager *Manager) GetSessionStore(sid string) (Store, error) { - s, err := (*session.Manager)(manager).GetSessionStore(sid) - return &NewToOldStoreAdapter{ - delegate: s, - }, err -} - -// GC Start session gc process. -// it can do gc in times after gc lifetime. -func (manager *Manager) GC() { - (*session.Manager)(manager).GC() -} - -// SessionRegenerateID Regenerate a session id for this SessionStore who's id is saving in http request. -func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Request) Store { - s, _ := (*session.Manager)(manager).SessionRegenerateID(w, r) - return &NewToOldStoreAdapter{ - delegate: s, - } -} - -// GetActiveSession Get all active sessions count number. -func (manager *Manager) GetActiveSession() int { - return (*session.Manager)(manager).GetActiveSession() -} - -// SetSecure Set cookie with https. -func (manager *Manager) SetSecure(secure bool) { - (*session.Manager)(manager).SetSecure(secure) -} - -// Log implement the log.Logger -type Log session.Log - -// NewSessionLog set io.Writer to create a Logger for session. -func NewSessionLog(out io.Writer) *Log { - return (*Log)(session.NewSessionLog(out)) -} diff --git a/adapter/session/ssdb/sess_ssdb.go b/adapter/session/ssdb/sess_ssdb.go deleted file mode 100644 index 9d08b2ab..00000000 --- a/adapter/session/ssdb/sess_ssdb.go +++ /dev/null @@ -1,83 +0,0 @@ -package ssdb - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/adapter/session" - beeSsdb "github.com/beego/beego/v2/server/web/session/ssdb" -) - -// Provider holds ssdb client and configs -type Provider beeSsdb.Provider - -// SessionInit init the ssdb with the config -func (p *Provider) SessionInit(maxLifetime int64, savePath string) error { - return (*beeSsdb.Provider)(p).SessionInit(context.Background(), maxLifetime, savePath) -} - -// SessionRead return a ssdb client session Store -func (p *Provider) SessionRead(sid string) (session.Store, error) { - s, err := (*beeSsdb.Provider)(p).SessionRead(context.Background(), sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionExist judged whether sid is exist in session -func (p *Provider) SessionExist(sid string) bool { - res, _ := (*beeSsdb.Provider)(p).SessionExist(context.Background(), sid) - return res -} - -// SessionRegenerate regenerate session with new sid and delete oldsid -func (p *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { - s, err := (*beeSsdb.Provider)(p).SessionRegenerate(context.Background(), oldsid, sid) - return session.CreateNewToOldStoreAdapter(s), err -} - -// SessionDestroy destroy the sid -func (p *Provider) SessionDestroy(sid string) error { - return (*beeSsdb.Provider)(p).SessionDestroy(context.Background(), sid) -} - -// SessionGC not implemented -func (p *Provider) SessionGC() { - (*beeSsdb.Provider)(p).SessionGC(context.Background()) -} - -// SessionAll not implemented -func (p *Provider) SessionAll() int { - return (*beeSsdb.Provider)(p).SessionAll(context.Background()) -} - -// SessionStore holds the session information which stored in ssdb -type SessionStore beeSsdb.SessionStore - -// Set the key and value -func (s *SessionStore) Set(key, value interface{}) error { - return (*beeSsdb.SessionStore)(s).Set(context.Background(), key, value) -} - -// Get return the value by the key -func (s *SessionStore) Get(key interface{}) interface{} { - return (*beeSsdb.SessionStore)(s).Get(context.Background(), key) -} - -// Delete the key in session store -func (s *SessionStore) Delete(key interface{}) error { - return (*beeSsdb.SessionStore)(s).Delete(context.Background(), key) -} - -// Flush delete all keys and values -func (s *SessionStore) Flush() error { - return (*beeSsdb.SessionStore)(s).Flush(context.Background()) -} - -// SessionID return the sessionID -func (s *SessionStore) SessionID() string { - return (*beeSsdb.SessionStore)(s).SessionID(context.Background()) -} - -// SessionRelease Store the keyvalues into ssdb -func (s *SessionStore) SessionRelease(w http.ResponseWriter) { - (*beeSsdb.SessionStore)(s).SessionRelease(context.Background(), w) -} diff --git a/adapter/session/store_adapter.go b/adapter/session/store_adapter.go deleted file mode 100644 index a459e68c..00000000 --- a/adapter/session/store_adapter.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2020 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package session - -import ( - "context" - "net/http" - - "github.com/beego/beego/v2/server/web/session" -) - -type NewToOldStoreAdapter struct { - delegate session.Store -} - -func CreateNewToOldStoreAdapter(s session.Store) Store { - return &NewToOldStoreAdapter{ - delegate: s, - } -} - -func (n *NewToOldStoreAdapter) Set(key, value interface{}) error { - return n.delegate.Set(context.Background(), key, value) -} - -func (n *NewToOldStoreAdapter) Get(key interface{}) interface{} { - return n.delegate.Get(context.Background(), key) -} - -func (n *NewToOldStoreAdapter) Delete(key interface{}) error { - return n.delegate.Delete(context.Background(), key) -} - -func (n *NewToOldStoreAdapter) SessionID() string { - return n.delegate.SessionID(context.Background()) -} - -func (n *NewToOldStoreAdapter) SessionRelease(w http.ResponseWriter) { - n.delegate.SessionRelease(context.Background(), w) -} - -func (n *NewToOldStoreAdapter) Flush() error { - return n.delegate.Flush(context.Background()) -} - -type oldToNewStoreAdapter struct { - delegate Store -} - -func (o *oldToNewStoreAdapter) Set(ctx context.Context, key, value interface{}) error { - return o.delegate.Set(key, value) -} - -func (o *oldToNewStoreAdapter) Get(ctx context.Context, key interface{}) interface{} { - return o.delegate.Get(key) -} - -func (o *oldToNewStoreAdapter) Delete(ctx context.Context, key interface{}) error { - return o.delegate.Delete(key) -} - -func (o *oldToNewStoreAdapter) SessionID(ctx context.Context) string { - return o.delegate.SessionID() -} - -func (o *oldToNewStoreAdapter) SessionRelease(ctx context.Context, w http.ResponseWriter) { - o.delegate.SessionRelease(w) -} - -func (o *oldToNewStoreAdapter) Flush(ctx context.Context) error { - return o.delegate.Flush() -} diff --git a/adapter/swagger/swagger.go b/adapter/swagger/swagger.go deleted file mode 100644 index fbb00bb4..00000000 --- a/adapter/swagger/swagger.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Swagger™ is a project used to describe and document RESTful APIs. -// -// The Swagger specification defines a set of files required to describe such an API. These files can then be used by the Swagger-UI project to display the API and Swagger-Codegen to generate clients in various languages. Additional utilities can also take advantage of the resulting files, such as testing tools. -// Now in version 2.0, Swagger is more enabling than ever. And it's 100% open source software. - -// Package swagger struct definition -package swagger - -import ( - "github.com/beego/beego/v2/server/web/swagger" -) - -// Swagger list the resource -type Swagger swagger.Swagger - -// Information Provides metadata about the API. The metadata can be used by the clients if needed. -type Information swagger.Information - -// Contact information for the exposed API. -type Contact swagger.Contact - -// License information for the exposed API. -type License swagger.License - -// Item Describes the operations available on a single path. -type Item swagger.Item - -// Operation Describes a single API operation on a path. -type Operation swagger.Operation - -// Parameter Describes a single operation parameter. -type Parameter swagger.Parameter - -// ParameterItems A limited subset of JSON-Schema's items object. It is used by parameter definitions that are not located in "body". -// http://swagger.io/specification/#itemsObject -type ParameterItems swagger.ParameterItems - -// Schema Object allows the definition of input and output data types. -type Schema swagger.Schema - -// Propertie are taken from the JSON Schema definition but their definitions were adjusted to the Swagger Specification -type Propertie swagger.Propertie - -// Response as they are returned from executing this operation. -type Response swagger.Response - -// Security Allows the definition of a security scheme that can be used by the operations -type Security swagger.Security - -// Tag Allows adding meta data to a single tag that is used by the Operation Object -type Tag swagger.Tag - -// ExternalDocs include Additional external documentation -type ExternalDocs swagger.ExternalDocs diff --git a/adapter/template.go b/adapter/template.go deleted file mode 100644 index 5957a0eb..00000000 --- a/adapter/template.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "html/template" - "io" - "net/http" - - "github.com/beego/beego/v2/server/web" -) - -// ExecuteTemplate applies the template with name to the specified data object, -// writing the output to wr. -// A template will be executed safely in parallel. -func ExecuteTemplate(wr io.Writer, name string, data interface{}) error { - return web.ExecuteTemplate(wr, name, data) -} - -// ExecuteViewPathTemplate applies the template with name and from specific viewPath to the specified data object, -// writing the output to wr. -// A template will be executed safely in parallel. -func ExecuteViewPathTemplate(wr io.Writer, name string, viewPath string, data interface{}) error { - return web.ExecuteViewPathTemplate(wr, name, viewPath, data) -} - -// AddFuncMap let user to register a func in the template. -func AddFuncMap(key string, fn interface{}) error { - return web.AddFuncMap(key, fn) -} - -type templatePreProcessor func(root, path string, funcs template.FuncMap) (*template.Template, error) - -type templateFile struct { - root string - files map[string][]string -} - -// HasTemplateExt return this path contains supported template extension of beego or not. -func HasTemplateExt(paths string) bool { - return web.HasTemplateExt(paths) -} - -// AddTemplateExt add new extension for template. -func AddTemplateExt(ext string) { - web.AddTemplateExt(ext) -} - -// AddViewPath adds a new path to the supported view paths. -// Can later be used by setting a controller ViewPath to this folder -// will panic if called after beego.Run() -func AddViewPath(viewPath string) error { - return web.AddViewPath(viewPath) -} - -// BuildTemplate will build all template files in a directory. -// it makes beego can render any template file in view directory. -func BuildTemplate(dir string, files ...string) error { - return web.BuildTemplate(dir, files...) -} - -type templateFSFunc func() http.FileSystem - -func defaultFSFunc() http.FileSystem { - return FileSystem{} -} - -// SetTemplateFSFunc set default filesystem function -func SetTemplateFSFunc(fnt templateFSFunc) { - web.SetTemplateFSFunc(func() http.FileSystem { - return fnt() - }) -} - -// SetViewsPath sets view directory path in beego application. -func SetViewsPath(path string) *App { - return (*App)(web.SetViewsPath(path)) -} - -// SetStaticPath sets static directory path and proper url pattern in beego application. -// if beego.SetStaticPath("static","public"), visit /static/* to load static file in folder "public". -func SetStaticPath(url string, path string) *App { - return (*App)(web.SetStaticPath(url, path)) -} - -// DelStaticPath removes the static folder setting in this url pattern in beego application. -func DelStaticPath(url string) *App { - return (*App)(web.DelStaticPath(url)) -} - -// AddTemplateEngine add a new templatePreProcessor which support extension -func AddTemplateEngine(extension string, fn templatePreProcessor) *App { - return (*App)(web.AddTemplateEngine(extension, func(root, path string, funcs template.FuncMap) (*template.Template, error) { - return fn(root, path, funcs) - })) -} diff --git a/adapter/templatefunc.go b/adapter/templatefunc.go deleted file mode 100644 index 32a250d1..00000000 --- a/adapter/templatefunc.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "html/template" - "net/url" - "time" - - "github.com/beego/beego/v2/server/web" -) - -const ( - formatTime = "15:04:05" - formatDate = "2006-01-02" - formatDateTime = "2006-01-02 15:04:05" - formatDateTimeT = "2006-01-02T15:04:05" -) - -// Substr returns the substr from start to length. -func Substr(s string, start, length int) string { - return web.Substr(s, start, length) -} - -// HTML2str returns escaping text convert from html. -func HTML2str(html string) string { - return web.HTML2str(html) -} - -// DateFormat takes a time and a layout string and returns a string with the formatted date. Used by the template parser as "dateformat" -func DateFormat(t time.Time, layout string) (datestring string) { - return web.DateFormat(t, layout) -} - -// DateParse Parse Date use PHP time format. -func DateParse(dateString, format string) (time.Time, error) { - return web.DateParse(dateString, format) -} - -// Date takes a PHP like date func to Go's time format. -func Date(t time.Time, format string) string { - return web.Date(t, format) -} - -// Compare is a quick and dirty comparison function. It will convert whatever you give it to strings and see if the two values are equal. -// Whitespace is trimmed. Used by the template parser as "eq". -func Compare(a, b interface{}) (equal bool) { - return web.Compare(a, b) -} - -// CompareNot !Compare -func CompareNot(a, b interface{}) (equal bool) { - return web.CompareNot(a, b) -} - -// NotNil the same as CompareNot -func NotNil(a interface{}) (isNil bool) { - return web.NotNil(a) -} - -// GetConfig get the Appconfig -func GetConfig(returnType, key string, defaultVal interface{}) (interface{}, error) { - return web.GetConfig(returnType, key, defaultVal) -} - -// Str2html Convert string to template.HTML type. -func Str2html(raw string) template.HTML { - return web.Str2html(raw) -} - -// Htmlquote returns quoted html string. -func Htmlquote(text string) string { - return web.Htmlquote(text) -} - -// Htmlunquote returns unquoted html string. -func Htmlunquote(text string) string { - return web.Htmlunquote(text) -} - -// URLFor returns url string with another registered controller handler with params. -// usage: -// -// URLFor(".index") -// print URLFor("index") -// router /login -// print URLFor("login") -// print URLFor("login", "next","/"") -// router /profile/:username -// print UrlFor("profile", ":username","John Doe") -// result: -// / -// /login -// /login?next=/ -// /user/John%20Doe -// -func URLFor(endpoint string, values ...interface{}) string { - return web.URLFor(endpoint, values...) -} - -// AssetsJs returns script tag with src string. -func AssetsJs(text string) template.HTML { - return web.AssetsJs(text) -} - -// AssetsCSS returns stylesheet link tag with src string. -func AssetsCSS(text string) template.HTML { - text = "" - - return template.HTML(text) -} - -// ParseForm will parse form values to struct via tag. -func ParseForm(form url.Values, obj interface{}) error { - return web.ParseForm(form, obj) -} - -// RenderForm will render object to form html. -// obj must be a struct pointer. -func RenderForm(obj interface{}) template.HTML { - return web.RenderForm(obj) -} - -// MapGet getting value from map by keys -// usage: -// Data["m"] = M{ -// "a": 1, -// "1": map[string]float64{ -// "c": 4, -// }, -// } -// -// {{ map_get m "a" }} // return 1 -// {{ map_get m 1 "c" }} // return 4 -func MapGet(arg1 interface{}, arg2 ...interface{}) (interface{}, error) { - return web.MapGet(arg1, arg2...) -} diff --git a/adapter/templatefunc_test.go b/adapter/templatefunc_test.go deleted file mode 100644 index b3d5e968..00000000 --- a/adapter/templatefunc_test.go +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "html/template" - "net/url" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestSubstr(t *testing.T) { - s := `012345` - assert.Equal(t, "01", Substr(s, 0, 2)) - assert.Equal(t, "012345", Substr(s, 0, 100)) - assert.Equal(t, "012345", Substr(s, 12, 100)) -} - -func TestHtml2str(t *testing.T) { - h := `<123> 123\n - - - \n` - assert.Equal(t, "123\\n\n\\n", HTML2str(h)) -} - -func TestDateFormat(t *testing.T) { - ts := "Mon, 01 Jul 2013 13:27:42 CST" - tt, _ := time.Parse(time.RFC1123, ts) - - assert.Equal(t, "2013-07-01 13:27:42", DateFormat(tt, "2006-01-02 15:04:05")) -} - -func TestDate(t *testing.T) { - ts := "Mon, 01 Jul 2013 13:27:42 CST" - tt, _ := time.Parse(time.RFC1123, ts) - - assert.Equal(t, "2013-07-01 13:27:42", Date(tt, "Y-m-d H:i:s")) - - assert.Equal(t, "13-7-1 01:27:42 PM", Date(tt, "y-n-j h:i:s A")) - assert.Equal(t, "Mon, 01 Jul 2013 1:27:42 pm", Date(tt, "D, d M Y g:i:s a")) - assert.Equal(t, "Monday, 01 July 2013 13:27:42", Date(tt, "l, d F Y G:i:s")) -} - -func TestCompareRelated(t *testing.T) { - assert.True(t, Compare("abc", "abc")) - - assert.False(t, Compare("abc", "aBc")) - - assert.True(t, Compare("1", 1)) - - assert.False(t, CompareNot("abc", "abc")) - - assert.True(t, CompareNot("abc", "aBc")) - assert.True(t, NotNil("a string")) -} - -func TestHtmlquote(t *testing.T) { - h := `<' ”“&">` - s := `<' ”“&">` - assert.Equal(t, h, Htmlquote(s)) -} - -func TestHtmlunquote(t *testing.T) { - h := `<' ”“&">` - s := `<' ”“&">` - assert.Equal(t, s, Htmlunquote(h)) -} - -func TestParseForm(t *testing.T) { - type ExtendInfo struct { - Hobby []string `form:"hobby"` - Memo string - } - - type OtherInfo struct { - Organization string `form:"organization"` - Title string `form:"title"` - ExtendInfo - } - - type user struct { - ID int `form:"-"` - tag string `form:"tag"` - Name interface{} `form:"username"` - Age int `form:"age,text"` - Email string - Intro string `form:",textarea"` - StrBool bool `form:"strbool"` - Date time.Time `form:"date,2006-01-02"` - OtherInfo - } - - u := user{} - form := url.Values{ - "ID": []string{"1"}, - "-": []string{"1"}, - "tag": []string{"no"}, - "username": []string{"test"}, - "age": []string{"40"}, - "Email": []string{"test@gmail.com"}, - "Intro": []string{"I am an engineer!"}, - "strbool": []string{"yes"}, - "date": []string{"2014-11-12"}, - "organization": []string{"beego"}, - "title": []string{"CXO"}, - "hobby": []string{"", "Basketball", "Football"}, - "memo": []string{"nothing"}, - } - - assert.NotNil(t, ParseForm(form, u)) - - assert.Nil(t, ParseForm(form, &u)) - - assert.Equal(t, 0, u.ID) - - assert.Equal(t, 0, len(u.tag)) - - assert.Equal(t, "test", u.Name) - - assert.Equal(t, 40, u.Age) - - assert.Equal(t, "test@gmail.com", u.Email) - - assert.Equal(t, "I am an engineer!", u.Intro) - - assert.True(t, u.StrBool) - - y, m, d := u.Date.Date() - - assert.Equal(t, 2014, y) - assert.Equal(t, "November", m.String()) - assert.Equal(t, 12, d) - - assert.Equal(t, "beego", u.Organization) - - assert.Equal(t, "CXO", u.Title) - - assert.Equal(t, "", u.Hobby[0]) - - assert.Equal(t, "Basketball", u.Hobby[1]) - - assert.Equal(t, "Football", u.Hobby[2]) - - assert.Equal(t, 0, len(u.Memo)) -} - -func TestRenderForm(t *testing.T) { - type user struct { - ID int `form:"-"` - Name interface{} `form:"username"` - Age int `form:"age,text,年龄:"` - Sex string - Email []string - Intro string `form:",textarea"` - Ignored string `form:"-"` - } - - u := user{Name: "test", Intro: "Some Text"} - output := RenderForm(u) - assert.Equal(t, template.HTML(""), output) - output = RenderForm(&u) - result := template.HTML( - `Name:
` + - `年龄:
` + - `Sex:
` + - `Intro: `) - assert.Equal(t, result, output) -} - -func TestMapGet(t *testing.T) { - // test one level map - m1 := map[string]int64{ - "a": 1, - "1": 2, - } - - res, err := MapGet(m1, "a") - assert.Nil(t, err) - assert.Equal(t, int64(1), res) - - res, err = MapGet(m1, "1") - assert.Nil(t, err) - assert.Equal(t, int64(2), res) - - res, err = MapGet(m1, 1) - assert.Nil(t, err) - assert.Equal(t, int64(2), res) - - // test 2 level map - m2 := M{ - "1": map[string]float64{ - "2": 3.5, - }, - } - - res, err = MapGet(m2, 1, 2) - assert.Nil(t, err) - assert.Equal(t, 3.5, res) - - // test 5 level map - m5 := M{ - "1": M{ - "2": M{ - "3": M{ - "4": M{ - "5": 1.2, - }, - }, - }, - }, - } - - res, err = MapGet(m5, 1, 2, 3, 4, 5) - assert.Nil(t, err) - assert.Equal(t, 1.2, res) - - // check whether element not exists in map - res, err = MapGet(m5, 5, 4, 3, 2, 1) - assert.Nil(t, err) - assert.Nil(t, res) -} diff --git a/adapter/testing/client.go b/adapter/testing/client.go deleted file mode 100644 index a773c9a6..00000000 --- a/adapter/testing/client.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package testing - -import "github.com/beego/beego/v2/client/httplib/testing" - -// TestHTTPRequest beego test request client -type TestHTTPRequest testing.TestHTTPRequest - -// Get returns test client in GET method -func Get(path string) *TestHTTPRequest { - return (*TestHTTPRequest)(testing.Get(path)) -} - -// Post returns test client in POST method -func Post(path string) *TestHTTPRequest { - return (*TestHTTPRequest)(testing.Post(path)) -} - -// Put returns test client in PUT method -func Put(path string) *TestHTTPRequest { - return (*TestHTTPRequest)(testing.Put(path)) -} - -// Delete returns test client in DELETE method -func Delete(path string) *TestHTTPRequest { - return (*TestHTTPRequest)(testing.Delete(path)) -} - -// Head returns test client in HEAD method -func Head(path string) *TestHTTPRequest { - return (*TestHTTPRequest)(testing.Head(path)) -} diff --git a/adapter/toolbox/healthcheck.go b/adapter/toolbox/healthcheck.go deleted file mode 100644 index 400e707e..00000000 --- a/adapter/toolbox/healthcheck.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package toolbox healthcheck -// -// type DatabaseCheck struct { -// } -// -// func (dc *DatabaseCheck) Check() error { -// if dc.isConnected() { -// return nil -// } else { -// return errors.New("can't connect database") -// } -// } -// -// AddHealthCheck("database",&DatabaseCheck{}) -// -package toolbox - -import ( - "github.com/beego/beego/v2/core/admin" -) - -// AdminCheckList holds health checker map -// Deprecated using admin.AdminCheckList -var AdminCheckList map[string]HealthChecker - -// HealthChecker health checker interface -type HealthChecker admin.HealthChecker - -// AddHealthCheck add health checker with name string -func AddHealthCheck(name string, hc HealthChecker) { - admin.AddHealthCheck(name, hc) - AdminCheckList[name] = hc -} - -func init() { - AdminCheckList = make(map[string]HealthChecker) -} diff --git a/adapter/toolbox/profile.go b/adapter/toolbox/profile.go deleted file mode 100644 index 00b0eef7..00000000 --- a/adapter/toolbox/profile.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package toolbox - -import ( - "io" - - "github.com/beego/beego/v2/core/admin" -) - -// ProcessInput parse input command string -func ProcessInput(input string, w io.Writer) { - admin.ProcessInput(input, w) -} - -// MemProf record memory profile in pprof -func MemProf(w io.Writer) { - admin.MemProf(w) -} - -// GetCPUProfile start cpu profile monitor -func GetCPUProfile(w io.Writer) { - admin.GetCPUProfile(w) -} - -// PrintGCSummary print gc information to io.Writer -func PrintGCSummary(w io.Writer) { - admin.PrintGCSummary(w) -} diff --git a/adapter/toolbox/profile_test.go b/adapter/toolbox/profile_test.go deleted file mode 100644 index 07a20c4e..00000000 --- a/adapter/toolbox/profile_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package toolbox - -import ( - "os" - "testing" -) - -func TestProcessInput(t *testing.T) { - ProcessInput("lookup goroutine", os.Stdout) - ProcessInput("lookup heap", os.Stdout) - ProcessInput("lookup threadcreate", os.Stdout) - ProcessInput("lookup block", os.Stdout) - ProcessInput("gc summary", os.Stdout) -} diff --git a/adapter/toolbox/statistics.go b/adapter/toolbox/statistics.go deleted file mode 100644 index 47bfbbd5..00000000 --- a/adapter/toolbox/statistics.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package toolbox - -import ( - "time" - - "github.com/beego/beego/v2/server/web" -) - -// Statistics struct -type Statistics web.Statistics - -// URLMap contains several statistics struct to log different data -type URLMap web.URLMap - -// AddStatistics add statistics task. -// it needs request method, request url, request controller and statistics time duration -func (m *URLMap) AddStatistics(requestMethod, requestURL, requestController string, requesttime time.Duration) { - (*web.URLMap)(m).AddStatistics(requestMethod, requestURL, requestController, requesttime) -} - -// GetMap put url statistics result in io.Writer -func (m *URLMap) GetMap() map[string]interface{} { - return (*web.URLMap)(m).GetMap() -} - -// GetMapData return all mapdata -func (m *URLMap) GetMapData() []map[string]interface{} { - return (*web.URLMap)(m).GetMapData() -} - -// StatisticsMap hosld global statistics data map -var StatisticsMap *URLMap - -func init() { - StatisticsMap = (*URLMap)(web.StatisticsMap) -} diff --git a/adapter/toolbox/statistics_test.go b/adapter/toolbox/statistics_test.go deleted file mode 100644 index f4371c3f..00000000 --- a/adapter/toolbox/statistics_test.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package toolbox - -import ( - "encoding/json" - "testing" - "time" -) - -func TestStatics(t *testing.T) { - userApi := "/api/user" - post := "POST" - adminUser := "&admin.user" - StatisticsMap.AddStatistics(post, userApi, adminUser, time.Duration(2000)) - StatisticsMap.AddStatistics(post, userApi, adminUser, time.Duration(120000)) - StatisticsMap.AddStatistics("GET", userApi, adminUser, time.Duration(13000)) - StatisticsMap.AddStatistics(post, "/api/admin", adminUser, time.Duration(14000)) - StatisticsMap.AddStatistics(post, "/api/user/astaxie", adminUser, time.Duration(12000)) - StatisticsMap.AddStatistics(post, "/api/user/xiemengjun", adminUser, time.Duration(13000)) - StatisticsMap.AddStatistics("DELETE", userApi, adminUser, time.Duration(1400)) - t.Log(StatisticsMap.GetMap()) - - data := StatisticsMap.GetMapData() - b, err := json.Marshal(data) - if err != nil { - t.Errorf(err.Error()) - } - - t.Log(string(b)) -} diff --git a/adapter/toolbox/task.go b/adapter/toolbox/task.go deleted file mode 100644 index 81864e9a..00000000 --- a/adapter/toolbox/task.go +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package toolbox - -import ( - "context" - "sort" - "time" - - "github.com/beego/beego/v2/task" -) - -// The bounds for each field. -var ( - AdminTaskList map[string]Tasker -) - -const ( - // Set the top bit if a star was included in the expression. - starBit = 1 << 63 -) - -// Schedule time taks schedule -type Schedule task.Schedule - -// TaskFunc task func type -type TaskFunc func() error - -// Tasker task interface -type Tasker interface { - GetSpec() string - GetStatus() string - Run() error - SetNext(time.Time) - GetNext() time.Time - SetPrev(time.Time) - GetPrev() time.Time -} - -// task error -type taskerr struct { - t time.Time - errinfo string -} - -// Task task struct -// Deprecated -type Task struct { - // Deprecated - Taskname string - // Deprecated - Spec *Schedule - // Deprecated - SpecStr string - // Deprecated - DoFunc TaskFunc - // Deprecated - Prev time.Time - // Deprecated - Next time.Time - // Deprecated - Errlist []*taskerr // like errtime:errinfo - // Deprecated - ErrLimit int // max length for the errlist, 0 stand for no limit - - delegate *task.Task -} - -// NewTask add new task with name, time and func -func NewTask(tname string, spec string, f TaskFunc) *Task { - task := task.NewTask(tname, spec, func(ctx context.Context) error { - return f() - }) - return &Task{ - delegate: task, - } -} - -// GetSpec get spec string -func (t *Task) GetSpec() string { - t.initDelegate() - - return t.delegate.GetSpec(context.Background()) -} - -// GetStatus get current task status -func (t *Task) GetStatus() string { - t.initDelegate() - - return t.delegate.GetStatus(context.Background()) -} - -// Run run all tasks -func (t *Task) Run() error { - t.initDelegate() - return t.delegate.Run(context.Background()) -} - -// SetNext set next time for this task -func (t *Task) SetNext(now time.Time) { - t.initDelegate() - t.delegate.SetNext(context.Background(), now) -} - -// GetNext get the next call time of this task -func (t *Task) GetNext() time.Time { - t.initDelegate() - return t.delegate.GetNext(context.Background()) -} - -// SetPrev set prev time of this task -func (t *Task) SetPrev(now time.Time) { - t.initDelegate() - t.delegate.SetPrev(context.Background(), now) -} - -// GetPrev get prev time of this task -func (t *Task) GetPrev() time.Time { - t.initDelegate() - return t.delegate.GetPrev(context.Background()) -} - -// six columns mean: -// second:0-59 -// minute:0-59 -// hour:1-23 -// day:1-31 -// month:1-12 -// week:0-6(0 means Sunday) - -// SetCron some signals: -// *: any time -// ,:  separate signal -//    -:duration -// /n : do as n times of time duration -// /////////////////////////////////////////////////////// -// 0/30 * * * * * every 30s -// 0 43 21 * * * 21:43 -// 0 15 05 * * *    05:15 -// 0 0 17 * * * 17:00 -// 0 0 17 * * 1 17:00 in every Monday -// 0 0,10 17 * * 0,2,3 17:00 and 17:10 in every Sunday, Tuesday and Wednesday -// 0 0-10 17 1 * * 17:00 to 17:10 in 1 min duration each time on the first day of month -// 0 0 0 1,15 * 1 0:00 on the 1st day and 15th day of month -// 0 42 4 1 * *     4:42 on the 1st day of month -// 0 0 21 * * 1-6   21:00 from Monday to Saturday -// 0 0,10,20,30,40,50 * * * *  every 10 min duration -// 0 */10 * * * *        every 10 min duration -// 0 * 1 * * *         1:00 to 1:59 in 1 min duration each time -// 0 0 1 * * *         1:00 -// 0 0 */1 * * *        0 min of hour in 1 hour duration -// 0 0 * * * *         0 min of hour in 1 hour duration -// 0 2 8-20/3 * * *       8:02, 11:02, 14:02, 17:02, 20:02 -// 0 30 5 1,15 * *       5:30 on the 1st day and 15th day of month -func (t *Task) SetCron(spec string) { - t.initDelegate() - t.delegate.SetCron(spec) -} - -func (t *Task) initDelegate() { - if t.delegate == nil { - t.delegate = &task.Task{ - Taskname: t.Taskname, - Spec: (*task.Schedule)(t.Spec), - SpecStr: t.SpecStr, - DoFunc: func(ctx context.Context) error { - return t.DoFunc() - }, - Prev: t.Prev, - Next: t.Next, - ErrLimit: t.ErrLimit, - } - } -} - -// Next set schedule to next time -func (s *Schedule) Next(t time.Time) time.Time { - return (*task.Schedule)(s).Next(t) -} - -// StartTask start all tasks -func StartTask() { - task.StartTask() -} - -// StopTask stop all tasks -func StopTask() { - task.StopTask() -} - -// AddTask add task with name -func AddTask(taskname string, t Tasker) { - task.AddTask(taskname, &oldToNewAdapter{delegate: t}) -} - -// DeleteTask delete task with name -func DeleteTask(taskname string) { - task.DeleteTask(taskname) -} - -// ClearTask clear all tasks -func ClearTask() { - task.ClearTask() -} - -// MapSorter sort map for tasker -type MapSorter task.MapSorter - -// NewMapSorter create new tasker map -func NewMapSorter(m map[string]Tasker) *MapSorter { - newTaskerMap := make(map[string]task.Tasker, len(m)) - - for key, value := range m { - newTaskerMap[key] = &oldToNewAdapter{ - delegate: value, - } - } - - return (*MapSorter)(task.NewMapSorter(newTaskerMap)) -} - -// Sort sort tasker map -func (ms *MapSorter) Sort() { - sort.Sort(ms) -} - -func (ms *MapSorter) Len() int { return len(ms.Keys) } - -func (ms *MapSorter) Less(i, j int) bool { - if ms.Vals[i].GetNext(context.Background()).IsZero() { - return false - } - if ms.Vals[j].GetNext(context.Background()).IsZero() { - return true - } - return ms.Vals[i].GetNext(context.Background()).Before(ms.Vals[j].GetNext(context.Background())) -} - -func (ms *MapSorter) Swap(i, j int) { - ms.Vals[i], ms.Vals[j] = ms.Vals[j], ms.Vals[i] - ms.Keys[i], ms.Keys[j] = ms.Keys[j], ms.Keys[i] -} - -func init() { - AdminTaskList = make(map[string]Tasker) -} - -type oldToNewAdapter struct { - delegate Tasker -} - -func (o *oldToNewAdapter) GetSpec(ctx context.Context) string { - return o.delegate.GetSpec() -} - -func (o *oldToNewAdapter) GetStatus(ctx context.Context) string { - return o.delegate.GetStatus() -} - -func (o *oldToNewAdapter) Run(ctx context.Context) error { - return o.delegate.Run() -} - -func (o *oldToNewAdapter) SetNext(ctx context.Context, t time.Time) { - o.delegate.SetNext(t) -} - -func (o *oldToNewAdapter) GetNext(ctx context.Context) time.Time { - return o.delegate.GetNext() -} - -func (o *oldToNewAdapter) SetPrev(ctx context.Context, t time.Time) { - o.delegate.SetPrev(t) -} - -func (o *oldToNewAdapter) GetPrev(ctx context.Context) time.Time { - return o.delegate.GetPrev() -} - -func (o *oldToNewAdapter) GetTimeout(ctx context.Context) time.Duration { - return 0 -} diff --git a/adapter/tree.go b/adapter/tree.go deleted file mode 100644 index 3d22d9ac..00000000 --- a/adapter/tree.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adapter - -import ( - "github.com/beego/beego/v2/adapter/context" - "github.com/beego/beego/v2/server/web" - beecontext "github.com/beego/beego/v2/server/web/context" -) - -// Tree has three elements: FixRouter/wildcard/leaves -// fixRouter stores Fixed Router -// wildcard stores params -// leaves store the endpoint information -type Tree web.Tree - -// NewTree return a new Tree -func NewTree() *Tree { - return (*Tree)(web.NewTree()) -} - -// AddTree will add tree to the exist Tree -// prefix should has no params -func (t *Tree) AddTree(prefix string, tree *Tree) { - (*web.Tree)(t).AddTree(prefix, (*web.Tree)(tree)) -} - -// AddRouter call addseg function -func (t *Tree) AddRouter(pattern string, runObject interface{}) { - (*web.Tree)(t).AddRouter(pattern, runObject) -} - -// Match router to runObject & params -func (t *Tree) Match(pattern string, ctx *context.Context) (runObject interface{}) { - return (*web.Tree)(t).Match(pattern, (*beecontext.Context)(ctx)) -} diff --git a/adapter/utils/caller.go b/adapter/utils/caller.go deleted file mode 100644 index 7aec5000..00000000 --- a/adapter/utils/caller.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "github.com/beego/beego/v2/core/utils" -) - -// GetFuncName get function name -func GetFuncName(i interface{}) string { - return utils.GetFuncName(i) -} diff --git a/adapter/utils/caller_test.go b/adapter/utils/caller_test.go deleted file mode 100644 index 0675f0aa..00000000 --- a/adapter/utils/caller_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "strings" - "testing" -) - -func TestGetFuncName(t *testing.T) { - name := GetFuncName(TestGetFuncName) - t.Log(name) - if !strings.HasSuffix(name, ".TestGetFuncName") { - t.Error("get func name error") - } -} diff --git a/adapter/utils/captcha/LICENSE b/adapter/utils/captcha/LICENSE deleted file mode 100644 index 0ad73ae0..00000000 --- a/adapter/utils/captcha/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2011-2014 Dmitry Chestnykh - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/adapter/utils/captcha/README.md b/adapter/utils/captcha/README.md deleted file mode 100644 index 07a4dc4d..00000000 --- a/adapter/utils/captcha/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Captcha - -an example for use captcha - -``` -package controllers - -import ( - "github.com/beego/beego/v2" - "github.com/beego/beego/v2/client/cache" - "github.com/beego/beego/v2/server/web/captcha" -) - -var cpt *captcha.Captcha - -func init() { - // use beego cache system store the captcha data - store := cache.NewMemoryCache() - cpt = captcha.NewWithFilter("/captcha/", store) -} - -type MainController struct { - beego.Controller -} - -func (this *MainController) Get() { - this.TplName = "index.tpl" -} - -func (this *MainController) Post() { - this.TplName = "index.tpl" - - this.Data["Success"] = cpt.VerifyReq(this.Ctx.Request) -} -``` - -template usage - -``` -{{.Success}} -
- {{create_captcha}} - -
-``` diff --git a/adapter/utils/captcha/captcha.go b/adapter/utils/captcha/captcha.go deleted file mode 100644 index 7cdcab2d..00000000 --- a/adapter/utils/captcha/captcha.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package captcha implements generation and verification of image CAPTCHAs. -// an example for use captcha -// -// ``` -// package controllers -// -// import ( -// "github.com/beego/beego/v2" -// "github.com/beego/beego/v2/client/cache" -// "github.com/beego/beego/v2/server/web/captcha" -// ) -// -// var cpt *captcha.Captcha -// -// func init() { -// // use beego cache system store the captcha data -// store := cache.NewMemoryCache() -// cpt = captcha.NewWithFilter("/captcha/", store) -// } -// -// type MainController struct { -// beego.Controller -// } -// -// func (this *MainController) Get() { -// this.TplName = "index.tpl" -// } -// -// func (this *MainController) Post() { -// this.TplName = "index.tpl" -// -// this.Data["Success"] = cpt.VerifyReq(this.Ctx.Request) -// } -// ``` -// -// template usage -// -// ``` -// {{.Success}} -//
-// {{create_captcha}} -// -//
-// ``` -package captcha - -import ( - "html/template" - "net/http" - "time" - - "github.com/beego/beego/v2/adapter/cache" - "github.com/beego/beego/v2/adapter/context" - "github.com/beego/beego/v2/server/web/captcha" - beecontext "github.com/beego/beego/v2/server/web/context" -) - -var defaultChars = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} - -const ( - // default captcha attributes - challengeNums = 6 - expiration = 600 * time.Second - fieldIDName = "captcha_id" - fieldCaptchaName = "captcha" - cachePrefix = "captcha_" - defaultURLPrefix = "/captcha/" -) - -// Captcha struct -type Captcha captcha.Captcha - -// Handler beego filter handler for serve captcha image -func (c *Captcha) Handler(ctx *context.Context) { - (*captcha.Captcha)(c).Handler((*beecontext.Context)(ctx)) -} - -// CreateCaptchaHTML template func for output html -func (c *Captcha) CreateCaptchaHTML() template.HTML { - return (*captcha.Captcha)(c).CreateCaptchaHTML() -} - -// CreateCaptcha create a new captcha id -func (c *Captcha) CreateCaptcha() (string, error) { - return (*captcha.Captcha)(c).CreateCaptcha() -} - -// VerifyReq verify from a request -func (c *Captcha) VerifyReq(req *http.Request) bool { - return (*captcha.Captcha)(c).VerifyReq(req) -} - -// Verify direct verify id and challenge string -func (c *Captcha) Verify(id string, challenge string) (success bool) { - return (*captcha.Captcha)(c).Verify(id, challenge) -} - -// NewCaptcha create a new captcha.Captcha -func NewCaptcha(urlPrefix string, store cache.Cache) *Captcha { - return (*Captcha)(captcha.NewCaptcha(urlPrefix, cache.CreateOldToNewAdapter(store))) -} - -// NewWithFilter create a new captcha.Captcha and auto AddFilter for serve captacha image -// and add a template func for output html -func NewWithFilter(urlPrefix string, store cache.Cache) *Captcha { - return (*Captcha)(captcha.NewWithFilter(urlPrefix, cache.CreateOldToNewAdapter(store))) -} diff --git a/adapter/utils/captcha/image.go b/adapter/utils/captcha/image.go deleted file mode 100644 index c28beb3c..00000000 --- a/adapter/utils/captcha/image.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package captcha - -import ( - "io" - - "github.com/beego/beego/v2/server/web/captcha" -) - -// Image struct -type Image captcha.Image - -// NewImage returns a new captcha image of the given width and height with the -// given digits, where each digit must be in range 0-9. -func NewImage(digits []byte, width, height int) *Image { - return (*Image)(captcha.NewImage(digits, width, height)) -} - -// WriteTo writes captcha image in PNG format into the given writer. -func (m *Image) WriteTo(w io.Writer) (int64, error) { - return (*captcha.Image)(m).WriteTo(w) -} diff --git a/adapter/utils/captcha/image_test.go b/adapter/utils/captcha/image_test.go deleted file mode 100644 index 8e3b1306..00000000 --- a/adapter/utils/captcha/image_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package captcha - -import ( - "testing" - - "github.com/beego/beego/v2/adapter/utils" -) - -const ( - // Standard width and height of a captcha image. - stdWidth = 240 - stdHeight = 80 -) - -type byteCounter struct { - n int64 -} - -func (bc *byteCounter) Write(b []byte) (int, error) { - bc.n += int64(len(b)) - return len(b), nil -} - -func BenchmarkNewImage(b *testing.B) { - b.StopTimer() - d := utils.RandomCreateBytes(challengeNums, defaultChars...) - b.StartTimer() - for i := 0; i < b.N; i++ { - NewImage(d, stdWidth, stdHeight) - } -} - -func BenchmarkImageWriteTo(b *testing.B) { - b.StopTimer() - d := utils.RandomCreateBytes(challengeNums, defaultChars...) - b.StartTimer() - counter := &byteCounter{} - for i := 0; i < b.N; i++ { - img := NewImage(d, stdWidth, stdHeight) - img.WriteTo(counter) - b.SetBytes(counter.n) - counter.n = 0 - } -} diff --git a/adapter/utils/debug.go b/adapter/utils/debug.go deleted file mode 100644 index 3e4e3a27..00000000 --- a/adapter/utils/debug.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "github.com/beego/beego/v2/core/utils" -) - -// Display print the data in console -func Display(data ...interface{}) { - utils.Display(data...) -} - -// GetDisplayString return data print string -func GetDisplayString(data ...interface{}) string { - return utils.GetDisplayString(data...) -} - -// Stack get stack bytes -func Stack(skip int, indent string) []byte { - return utils.Stack(skip, indent) -} diff --git a/adapter/utils/debug_test.go b/adapter/utils/debug_test.go deleted file mode 100644 index a748d20a..00000000 --- a/adapter/utils/debug_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "testing" -) - -type mytype struct { - next *mytype - prev *mytype -} - -func TestPrint(t *testing.T) { - Display("v1", 1, "v2", 2, "v3", 3) -} - -func TestPrintPoint(t *testing.T) { - v1 := new(mytype) - v2 := new(mytype) - - v1.prev = nil - v1.next = v2 - - v2.prev = v1 - v2.next = nil - - Display("v1", v1, "v2", v2) -} - -func TestPrintString(t *testing.T) { - str := GetDisplayString("v1", 1, "v2", 2) - println(str) -} diff --git a/adapter/utils/file.go b/adapter/utils/file.go deleted file mode 100644 index e6a785a2..00000000 --- a/adapter/utils/file.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "github.com/beego/beego/v2/core/utils" -) - -// SelfPath gets compiled executable file absolute path -func SelfPath() string { - return utils.SelfPath() -} - -// SelfDir gets compiled executable file directory -func SelfDir() string { - return utils.SelfDir() -} - -// FileExists reports whether the named file or directory exists. -func FileExists(name string) bool { - return utils.FileExists(name) -} - -// SearchFile Search a file in paths. -// this is often used in search config file in /etc ~/ -func SearchFile(filename string, paths ...string) (fullpath string, err error) { - return utils.SearchFile(filename, paths...) -} - -// GrepFile like command grep -E -// for example: GrepFile(`^hello`, "hello.txt") -// \n is striped while read -func GrepFile(patten string, filename string) (lines []string, err error) { - return utils.GrepFile(patten, filename) -} diff --git a/adapter/utils/mail.go b/adapter/utils/mail.go deleted file mode 100644 index 4ef89660..00000000 --- a/adapter/utils/mail.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "io" - - "github.com/beego/beego/v2/core/utils" -) - -// Email is the type used for email messages -type Email utils.Email - -// Attachment is a struct representing an email attachment. -// Based on the mime/multipart.FileHeader struct, Attachment contains the name, MIMEHeader, and content of the attachment in question -type Attachment utils.Attachment - -// NewEMail create new Email struct with config json. -// config json is followed from Email struct fields. -func NewEMail(config string) *Email { - return (*Email)(utils.NewEMail(config)) -} - -// Bytes Make all send information to byte -func (e *Email) Bytes() ([]byte, error) { - return (*utils.Email)(e).Bytes() -} - -// AttachFile Add attach file to the send mail -func (e *Email) AttachFile(args ...string) (*Attachment, error) { - a, err := (*utils.Email)(e).AttachFile(args...) - if err != nil { - return nil, err - } - return (*Attachment)(a), err -} - -// Attach is used to attach content from an io.Reader to the email. -// Parameters include an io.Reader, the desired filename for the attachment, and the Content-Type. -func (e *Email) Attach(r io.Reader, filename string, args ...string) (*Attachment, error) { - a, err := (*utils.Email)(e).Attach(r, filename, args...) - if err != nil { - return nil, err - } - return (*Attachment)(a), err -} - -// Send will send out the mail -func (e *Email) Send() error { - return (*utils.Email)(e).Send() -} diff --git a/adapter/utils/mail_test.go b/adapter/utils/mail_test.go deleted file mode 100644 index c38356a2..00000000 --- a/adapter/utils/mail_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import "testing" - -func TestMail(t *testing.T) { - config := `{"username":"astaxie@gmail.com","password":"astaxie","host":"smtp.gmail.com","port":587}` - mail := NewEMail(config) - if mail.Username != "astaxie@gmail.com" { - t.Fatal("email parse get username error") - } - if mail.Password != "astaxie" { - t.Fatal("email parse get password error") - } - if mail.Host != "smtp.gmail.com" { - t.Fatal("email parse get host error") - } - if mail.Port != 587 { - t.Fatal("email parse get port error") - } - mail.To = []string{"xiemengjun@gmail.com"} - mail.From = "astaxie@gmail.com" - mail.Subject = "hi, just from beego!" - mail.Text = "Text Body is, of course, supported!" - mail.HTML = "

Fancy Html is supported, too!

" - mail.AttachFile("/Users/astaxie/github/beego/beego.go") - mail.Send() -} diff --git a/adapter/utils/pagination/controller.go b/adapter/utils/pagination/controller.go deleted file mode 100644 index ab3fb83d..00000000 --- a/adapter/utils/pagination/controller.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package pagination - -import ( - "github.com/beego/beego/v2/adapter/context" - beecontext "github.com/beego/beego/v2/server/web/context" - "github.com/beego/beego/v2/server/web/pagination" -) - -// SetPaginator Instantiates a Paginator and assigns it to context.Input.Data("paginator"). -func SetPaginator(ctx *context.Context, per int, nums int64) (paginator *Paginator) { - return (*Paginator)(pagination.SetPaginator((*beecontext.Context)(ctx), per, nums)) -} diff --git a/adapter/utils/pagination/doc.go b/adapter/utils/pagination/doc.go deleted file mode 100644 index 67530041..00000000 --- a/adapter/utils/pagination/doc.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -Package pagination provides utilities to setup a paginator within the -context of a http request. - -Usage - -In your beego.Controller: - - package controllers - - import "github.com/beego/beego/v2/server/web/pagination" - - type PostsController struct { - beego.Controller - } - - func (this *PostsController) ListAllPosts() { - // sets this.Data["paginator"] with the current offset (from the url query param) - postsPerPage := 20 - paginator := pagination.SetPaginator(this.Ctx, postsPerPage, CountPosts()) - - // fetch the next 20 posts - this.Data["posts"] = ListPostsByOffsetAndLimit(paginator.Offset(), postsPerPage) - } - - -In your view templates: - - {{if .paginator.HasPages}} - - {{end}} - -*/ -package pagination diff --git a/adapter/utils/pagination/paginator.go b/adapter/utils/pagination/paginator.go deleted file mode 100644 index cbf71da4..00000000 --- a/adapter/utils/pagination/paginator.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package pagination - -import ( - "net/http" - - "github.com/beego/beego/v2/core/utils/pagination" -) - -// Paginator within the state of a http request. -type Paginator pagination.Paginator - -// PageNums Returns the total number of pages. -func (p *Paginator) PageNums() int { - return (*pagination.Paginator)(p).PageNums() -} - -// Nums Returns the total number of items (e.g. from doing SQL count). -func (p *Paginator) Nums() int64 { - return (*pagination.Paginator)(p).Nums() -} - -// SetNums Sets the total number of items. -func (p *Paginator) SetNums(nums interface{}) { - (*pagination.Paginator)(p).SetNums(nums) -} - -// Page Returns the current page. -func (p *Paginator) Page() int { - return (*pagination.Paginator)(p).Page() -} - -// Pages Returns a list of all pages. -// -// Usage (in a view template): -// -// {{range $index, $page := .paginator.Pages}} -// -// {{$page}} -// -// {{end}} -func (p *Paginator) Pages() []int { - return (*pagination.Paginator)(p).Pages() -} - -// PageLink Returns URL for a given page index. -func (p *Paginator) PageLink(page int) string { - return (*pagination.Paginator)(p).PageLink(page) -} - -// PageLinkPrev Returns URL to the previous page. -func (p *Paginator) PageLinkPrev() (link string) { - return (*pagination.Paginator)(p).PageLinkPrev() -} - -// PageLinkNext Returns URL to the next page. -func (p *Paginator) PageLinkNext() (link string) { - return (*pagination.Paginator)(p).PageLinkNext() -} - -// PageLinkFirst Returns URL to the first page. -func (p *Paginator) PageLinkFirst() (link string) { - return (*pagination.Paginator)(p).PageLinkFirst() -} - -// PageLinkLast Returns URL to the last page. -func (p *Paginator) PageLinkLast() (link string) { - return (*pagination.Paginator)(p).PageLinkLast() -} - -// HasPrev Returns true if the current page has a predecessor. -func (p *Paginator) HasPrev() bool { - return (*pagination.Paginator)(p).HasPrev() -} - -// HasNext Returns true if the current page has a successor. -func (p *Paginator) HasNext() bool { - return (*pagination.Paginator)(p).HasNext() -} - -// IsActive Returns true if the given page index points to the current page. -func (p *Paginator) IsActive(page int) bool { - return (*pagination.Paginator)(p).IsActive(page) -} - -// Offset Returns the current offset. -func (p *Paginator) Offset() int { - return (*pagination.Paginator)(p).Offset() -} - -// HasPages Returns true if there is more than one page. -func (p *Paginator) HasPages() bool { - return (*pagination.Paginator)(p).HasPages() -} - -// NewPaginator Instantiates a paginator struct for the current http request. -func NewPaginator(req *http.Request, per int, nums interface{}) *Paginator { - return (*Paginator)(pagination.NewPaginator(req, per, nums)) -} diff --git a/adapter/utils/rand.go b/adapter/utils/rand.go deleted file mode 100644 index 2c22ac76..00000000 --- a/adapter/utils/rand.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "github.com/beego/beego/v2/core/utils" -) - -// RandomCreateBytes generate random []byte by specify chars. -func RandomCreateBytes(n int, alphabets ...byte) []byte { - return utils.RandomCreateBytes(n, alphabets...) -} diff --git a/adapter/utils/rand_test.go b/adapter/utils/rand_test.go deleted file mode 100644 index 1cb26029..00000000 --- a/adapter/utils/rand_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2016 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import "testing" - -func TestRand01(t *testing.T) { - bs0 := RandomCreateBytes(16) - bs1 := RandomCreateBytes(16) - - t.Log(string(bs0), string(bs1)) - if string(bs0) == string(bs1) { - t.FailNow() - } - - bs0 = RandomCreateBytes(4, []byte(`a`)...) - - if string(bs0) != "aaaa" { - t.FailNow() - } -} diff --git a/adapter/utils/safemap.go b/adapter/utils/safemap.go deleted file mode 100644 index 62bf811b..00000000 --- a/adapter/utils/safemap.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "github.com/beego/beego/v2/core/utils" -) - -// BeeMap is a map with lock -type BeeMap utils.BeeMap - -// NewBeeMap return new safemap -func NewBeeMap() *BeeMap { - return (*BeeMap)(utils.NewBeeMap()) -} - -// Get from maps return the k's value -func (m *BeeMap) Get(k interface{}) interface{} { - return (*utils.BeeMap)(m).Get(k) -} - -// Set Maps the given key and value. Returns false -// if the key is already in the map and changes nothing. -func (m *BeeMap) Set(k interface{}, v interface{}) bool { - return (*utils.BeeMap)(m).Set(k, v) -} - -// Check Returns true if k is exist in the map. -func (m *BeeMap) Check(k interface{}) bool { - return (*utils.BeeMap)(m).Check(k) -} - -// Delete the given key and value. -func (m *BeeMap) Delete(k interface{}) { - (*utils.BeeMap)(m).Delete(k) -} - -// Items returns all items in safemap. -func (m *BeeMap) Items() map[interface{}]interface{} { - return (*utils.BeeMap)(m).Items() -} - -// Count returns the number of items within the map. -func (m *BeeMap) Count() int { - return (*utils.BeeMap)(m).Count() -} diff --git a/adapter/utils/safemap_test.go b/adapter/utils/safemap_test.go deleted file mode 100644 index 65085195..00000000 --- a/adapter/utils/safemap_test.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import "testing" - -var safeMap *BeeMap - -func TestNewBeeMap(t *testing.T) { - safeMap = NewBeeMap() - if safeMap == nil { - t.Fatal("expected to return non-nil BeeMap", "got", safeMap) - } -} - -func TestSet(t *testing.T) { - safeMap = NewBeeMap() - if ok := safeMap.Set("astaxie", 1); !ok { - t.Error("expected", true, "got", false) - } -} - -func TestReSet(t *testing.T) { - safeMap := NewBeeMap() - if ok := safeMap.Set("astaxie", 1); !ok { - t.Error("expected", true, "got", false) - } - // set diff value - if ok := safeMap.Set("astaxie", -1); !ok { - t.Error("expected", true, "got", false) - } - - // set same value - if ok := safeMap.Set("astaxie", -1); ok { - t.Error("expected", false, "got", true) - } -} - -func TestCheck(t *testing.T) { - if exists := safeMap.Check("astaxie"); !exists { - t.Error("expected", true, "got", false) - } -} - -func TestGet(t *testing.T) { - if val := safeMap.Get("astaxie"); val.(int) != 1 { - t.Error("expected value", 1, "got", val) - } -} - -func TestDelete(t *testing.T) { - safeMap.Delete("astaxie") - if exists := safeMap.Check("astaxie"); exists { - t.Error("expected element to be deleted") - } -} - -func TestItems(t *testing.T) { - safeMap := NewBeeMap() - safeMap.Set("astaxie", "hello") - for k, v := range safeMap.Items() { - key := k.(string) - value := v.(string) - if key != "astaxie" { - t.Error("expected the key should be astaxie") - } - if value != "hello" { - t.Error("expected the value should be hello") - } - } -} - -func TestCount(t *testing.T) { - if count := safeMap.Count(); count != 0 { - t.Error("expected count to be", 0, "got", count) - } -} diff --git a/adapter/utils/slice.go b/adapter/utils/slice.go deleted file mode 100644 index 082b22ce..00000000 --- a/adapter/utils/slice.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "github.com/beego/beego/v2/core/utils" -) - -type reducetype func(interface{}) interface{} - -type filtertype func(interface{}) bool - -// InSlice checks given string in string slice or not. -func InSlice(v string, sl []string) bool { - return utils.InSlice(v, sl) -} - -// InSliceIface checks given interface in interface slice. -func InSliceIface(v interface{}, sl []interface{}) bool { - return utils.InSliceIface(v, sl) -} - -// SliceRandList generate an int slice from min to max. -func SliceRandList(min, max int) []int { - return utils.SliceRandList(min, max) -} - -// SliceMerge merges interface slices to one slice. -func SliceMerge(slice1, slice2 []interface{}) (c []interface{}) { - return utils.SliceMerge(slice1, slice2) -} - -// SliceReduce generates a new slice after parsing every value by reduce function -func SliceReduce(slice []interface{}, a reducetype) (dslice []interface{}) { - return utils.SliceReduce(slice, func(i interface{}) interface{} { - return a(i) - }) -} - -// SliceRand returns random one from slice. -func SliceRand(a []interface{}) (b interface{}) { - return utils.SliceRand(a) -} - -// SliceSum sums all values in int64 slice. -func SliceSum(intslice []int64) (sum int64) { - return utils.SliceSum(intslice) -} - -// SliceFilter generates a new slice after filter function. -func SliceFilter(slice []interface{}, a filtertype) (ftslice []interface{}) { - return utils.SliceFilter(slice, func(i interface{}) bool { - return a(i) - }) -} - -// SliceDiff returns diff slice of slice1 - slice2. -func SliceDiff(slice1, slice2 []interface{}) (diffslice []interface{}) { - return utils.SliceDiff(slice1, slice2) -} - -// SliceIntersect returns slice that are present in all the slice1 and slice2. -func SliceIntersect(slice1, slice2 []interface{}) (diffslice []interface{}) { - return utils.SliceIntersect(slice1, slice2) -} - -// SliceChunk separates one slice to some sized slice. -func SliceChunk(slice []interface{}, size int) (chunkslice [][]interface{}) { - return utils.SliceChunk(slice, size) -} - -// SliceRange generates a new slice from begin to end with step duration of int64 number. -func SliceRange(start, end, step int64) (intslice []int64) { - return utils.SliceRange(start, end, step) -} - -// SlicePad prepends size number of val into slice. -func SlicePad(slice []interface{}, size int, val interface{}) []interface{} { - return utils.SlicePad(slice, size, val) -} - -// SliceUnique cleans repeated values in slice. -func SliceUnique(slice []interface{}) (uniqueslice []interface{}) { - return utils.SliceUnique(slice) -} - -// SliceShuffle shuffles a slice. -func SliceShuffle(slice []interface{}) []interface{} { - return utils.SliceShuffle(slice) -} diff --git a/adapter/utils/slice_test.go b/adapter/utils/slice_test.go deleted file mode 100644 index 142dec96..00000000 --- a/adapter/utils/slice_test.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "testing" -) - -func TestInSlice(t *testing.T) { - sl := []string{"A", "b"} - if !InSlice("A", sl) { - t.Error("should be true") - } - if InSlice("B", sl) { - t.Error("should be false") - } -} diff --git a/adapter/utils/utils.go b/adapter/utils/utils.go deleted file mode 100644 index 235cc352..00000000 --- a/adapter/utils/utils.go +++ /dev/null @@ -1,10 +0,0 @@ -package utils - -import ( - "github.com/beego/beego/v2/core/utils" -) - -// GetGOPATHs returns all paths in GOPATH variable. -func GetGOPATHs() []string { - return utils.GetGOPATHs() -} diff --git a/adapter/validation/util.go b/adapter/validation/util.go deleted file mode 100644 index 5ff43ebc..00000000 --- a/adapter/validation/util.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validation - -import ( - "reflect" - - "github.com/beego/beego/v2/core/validation" -) - -const ( - // ValidTag struct tag - ValidTag = validation.ValidTag - - LabelTag = validation.LabelTag -) - -var ErrInt64On32 = validation.ErrInt64On32 - -// CustomFunc is for custom validate function -type CustomFunc func(v *Validation, obj interface{}, key string) - -// AddCustomFunc Add a custom function to validation -// The name can not be: -// Clear -// HasErrors -// ErrorMap -// Error -// Check -// Valid -// NoMatch -// If the name is same with exists function, it will replace the origin valid function -func AddCustomFunc(name string, f CustomFunc) error { - return validation.AddCustomFunc(name, func(v *validation.Validation, obj interface{}, key string) { - f((*Validation)(v), obj, key) - }) -} - -// ValidFunc Valid function type -type ValidFunc validation.ValidFunc - -// Funcs Validate function map -type Funcs validation.Funcs - -// Call validate values with named type string -func (f Funcs) Call(name string, params ...interface{}) (result []reflect.Value, err error) { - return (validation.Funcs(f)).Call(name, params...) -} diff --git a/adapter/validation/validation.go b/adapter/validation/validation.go deleted file mode 100644 index 0e7f9adf..00000000 --- a/adapter/validation/validation.go +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package validation for validations -// -// import ( -// "github.com/beego/beego/v2/core/validation" -// "log" -// ) -// -// type User struct { -// Name string -// Age int -// } -// -// func main() { -// u := User{"man", 40} -// valid := validation.Validation{} -// valid.Required(u.Name, "name") -// valid.MaxSize(u.Name, 15, "nameMax") -// valid.Range(u.Age, 0, 140, "age") -// if valid.HasErrors() { -// // validation does not pass -// // print invalid message -// for _, err := range valid.Errors { -// log.Println(err.Key, err.Message) -// } -// } -// // or use like this -// if v := valid.Max(u.Age, 140, "ageMax"); !v.Ok { -// log.Println(v.Error.Key, v.Error.Message) -// } -// } -// -package validation - -import ( - "fmt" - "regexp" - - "github.com/beego/beego/v2/core/validation" -) - -// ValidFormer valid interface -type ValidFormer interface { - Valid(*Validation) -} - -// Error show the error -type Error validation.Error - -// String Returns the Message. -func (e *Error) String() string { - if e == nil { - return "" - } - return e.Message -} - -// Implement Error interface. -// Return e.String() -func (e *Error) Error() string { return e.String() } - -// Result is returned from every validation method. -// It provides an indication of success, and a pointer to the Error (if any). -type Result validation.Result - -// Key Get Result by given key string. -func (r *Result) Key(key string) *Result { - if r.Error != nil { - r.Error.Key = key - } - return r -} - -// Message Set Result message by string or format string with args -func (r *Result) Message(message string, args ...interface{}) *Result { - if r.Error != nil { - if len(args) == 0 { - r.Error.Message = message - } else { - r.Error.Message = fmt.Sprintf(message, args...) - } - } - return r -} - -// A Validation context manages data validation and error messages. -type Validation validation.Validation - -// Clear Clean all ValidationError. -func (v *Validation) Clear() { - (*validation.Validation)(v).Clear() -} - -// HasErrors Has ValidationError nor not. -func (v *Validation) HasErrors() bool { - return (*validation.Validation)(v).HasErrors() -} - -// ErrorMap Return the errors mapped by key. -// If there are multiple validation errors associated with a single key, the -// first one "wins". (Typically the first validation will be the more basic). -func (v *Validation) ErrorMap() map[string][]*Error { - newErrors := (*validation.Validation)(v).ErrorMap() - res := make(map[string][]*Error, len(newErrors)) - for n, es := range newErrors { - errs := make([]*Error, 0, len(es)) - - for _, e := range es { - errs = append(errs, (*Error)(e)) - } - - res[n] = errs - } - return res -} - -// Error Add an error to the validation context. -func (v *Validation) Error(message string, args ...interface{}) *Result { - return (*Result)((*validation.Validation)(v).Error(message, args...)) -} - -// Required Test that the argument is non-nil and non-empty (if string or list) -func (v *Validation) Required(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).Required(obj, key)) -} - -// Min Test that the obj is greater than min if obj's type is int -func (v *Validation) Min(obj interface{}, min int, key string) *Result { - return (*Result)((*validation.Validation)(v).Min(obj, min, key)) -} - -// Max Test that the obj is less than max if obj's type is int -func (v *Validation) Max(obj interface{}, max int, key string) *Result { - return (*Result)((*validation.Validation)(v).Max(obj, max, key)) -} - -// Range Test that the obj is between mni and max if obj's type is int -func (v *Validation) Range(obj interface{}, min, max int, key string) *Result { - return (*Result)((*validation.Validation)(v).Range(obj, min, max, key)) -} - -// MinSize Test that the obj is longer than min size if type is string or slice -func (v *Validation) MinSize(obj interface{}, min int, key string) *Result { - return (*Result)((*validation.Validation)(v).MinSize(obj, min, key)) -} - -// MaxSize Test that the obj is shorter than max size if type is string or slice -func (v *Validation) MaxSize(obj interface{}, max int, key string) *Result { - return (*Result)((*validation.Validation)(v).MaxSize(obj, max, key)) -} - -// Length Test that the obj is same length to n if type is string or slice -func (v *Validation) Length(obj interface{}, n int, key string) *Result { - return (*Result)((*validation.Validation)(v).Length(obj, n, key)) -} - -// Alpha Test that the obj is [a-zA-Z] if type is string -func (v *Validation) Alpha(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).Alpha(obj, key)) -} - -// Numeric Test that the obj is [0-9] if type is string -func (v *Validation) Numeric(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).Numeric(obj, key)) -} - -// AlphaNumeric Test that the obj is [0-9a-zA-Z] if type is string -func (v *Validation) AlphaNumeric(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).AlphaNumeric(obj, key)) -} - -// Match Test that the obj matches regexp if type is string -func (v *Validation) Match(obj interface{}, regex *regexp.Regexp, key string) *Result { - return (*Result)((*validation.Validation)(v).Match(obj, regex, key)) -} - -// NoMatch Test that the obj doesn't match regexp if type is string -func (v *Validation) NoMatch(obj interface{}, regex *regexp.Regexp, key string) *Result { - return (*Result)((*validation.Validation)(v).NoMatch(obj, regex, key)) -} - -// AlphaDash Test that the obj is [0-9a-zA-Z_-] if type is string -func (v *Validation) AlphaDash(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).AlphaDash(obj, key)) -} - -// Email Test that the obj is email address if type is string -func (v *Validation) Email(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).Email(obj, key)) -} - -// IP Test that the obj is IP address if type is string -func (v *Validation) IP(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).IP(obj, key)) -} - -// Base64 Test that the obj is base64 encoded if type is string -func (v *Validation) Base64(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).Base64(obj, key)) -} - -// Mobile Test that the obj is chinese mobile number if type is string -func (v *Validation) Mobile(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).Mobile(obj, key)) -} - -// Tel Test that the obj is chinese telephone number if type is string -func (v *Validation) Tel(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).Tel(obj, key)) -} - -// Phone Test that the obj is chinese mobile or telephone number if type is string -func (v *Validation) Phone(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).Phone(obj, key)) -} - -// ZipCode Test that the obj is chinese zip code if type is string -func (v *Validation) ZipCode(obj interface{}, key string) *Result { - return (*Result)((*validation.Validation)(v).ZipCode(obj, key)) -} - -// key must like aa.bb.cc or aa.bb. -// AddError adds independent error message for the provided key -func (v *Validation) AddError(key, message string) { - (*validation.Validation)(v).AddError(key, message) -} - -// SetError Set error message for one field in ValidationError -func (v *Validation) SetError(fieldName string, errMsg string) *Error { - return (*Error)((*validation.Validation)(v).SetError(fieldName, errMsg)) -} - -// Check Apply a group of validators to a field, in order, and return the -// ValidationResult from the first one that fails, or the last one that -// succeeds. -func (v *Validation) Check(obj interface{}, checks ...Validator) *Result { - vldts := make([]validation.Validator, 0, len(checks)) - for _, v := range checks { - vldts = append(vldts, validation.Validator(v)) - } - return (*Result)((*validation.Validation)(v).Check(obj, vldts...)) -} - -// Valid Validate a struct. -// the obj parameter must be a struct or a struct pointer -func (v *Validation) Valid(obj interface{}) (b bool, err error) { - return (*validation.Validation)(v).Valid(obj) -} - -// RecursiveValid Recursively validate a struct. -// Step1: Validate by v.Valid -// Step2: If pass on step1, then reflect obj's fields -// Step3: Do the Recursively validation to all struct or struct pointer fields -func (v *Validation) RecursiveValid(objc interface{}) (bool, error) { - return (*validation.Validation)(v).RecursiveValid(objc) -} - -func (v *Validation) CanSkipAlso(skipFunc string) { - (*validation.Validation)(v).CanSkipAlso(skipFunc) -} diff --git a/adapter/validation/validation_test.go b/adapter/validation/validation_test.go deleted file mode 100644 index 547e8635..00000000 --- a/adapter/validation/validation_test.go +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validation - -import ( - "regexp" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestRequired(t *testing.T) { - valid := Validation{} - - assert.False(t, valid.Required(nil, "nil").Ok) - assert.True(t, valid.Required(true, "bool").Ok) - - assert.True(t, valid.Required(false, "bool").Ok) - assert.False(t, valid.Required("", "string").Ok) - assert.False(t, valid.Required(" ", "string").Ok) - assert.False(t, valid.Required("\n", "string").Ok) - - assert.True(t, valid.Required("astaxie", "string").Ok) - assert.False(t, valid.Required(0, "zero").Ok) - - assert.True(t, valid.Required(1, "int").Ok) - - assert.True(t, valid.Required(time.Now(), "time").Ok) - - assert.False(t, valid.Required([]string{}, "emptySlice").Ok) - - assert.True(t, valid.Required([]interface{}{"ok"}, "slice").Ok) -} - -func TestMin(t *testing.T) { - valid := Validation{} - - assert.False(t, valid.Min(-1, 0, "min0").Ok) - assert.True(t, valid.Min(1, 0, "min0").Ok) -} - -func TestMax(t *testing.T) { - valid := Validation{} - - assert.False(t, valid.Max(1, 0, "max0").Ok) - assert.True(t, valid.Max(-1, 0, "max0").Ok) -} - -func TestRange(t *testing.T) { - valid := Validation{} - - assert.False(t, valid.Range(-1, 0, 1, "range0_1").Ok) - - assert.True(t, valid.Range(1, 0, 1, "range0_1").Ok) -} - -func TestMinSize(t *testing.T) { - valid := Validation{} - - assert.False(t, valid.MinSize("", 1, "minSize1").Ok) - - assert.True(t, valid.MinSize("ok", 1, "minSize1").Ok) - assert.False(t, valid.MinSize([]string{}, 1, "minSize1").Ok) - assert.True(t, valid.MinSize([]interface{}{"ok"}, 1, "minSize1").Ok) -} - -func TestMaxSize(t *testing.T) { - valid := Validation{} - - assert.False(t, valid.MaxSize("ok", 1, "maxSize1").Ok) - assert.True(t, valid.MaxSize("", 1, "maxSize1").Ok) - assert.False(t, valid.MaxSize([]interface{}{"ok", false}, 1, "maxSize1").Ok) - assert.True(t, valid.MaxSize([]string{}, 1, "maxSize1").Ok) -} - -func TestLength(t *testing.T) { - valid := Validation{} - - assert.False(t, valid.Length("", 1, "length1").Ok) - assert.True(t, valid.Length("1", 1, "length1").Ok) - - assert.False(t, valid.Length([]string{}, 1, "length1").Ok) - assert.True(t, valid.Length([]interface{}{"ok"}, 1, "length1").Ok) -} - -func TestAlpha(t *testing.T) { - valid := Validation{} - - if valid.Alpha("a,1-@ $", "alpha").Ok { - t.Error("\"a,1-@ $\" are valid alpha characters should be false") - } - if !valid.Alpha("abCD", "alpha").Ok { - t.Error("\"abCD\" are valid alpha characters should be true") - } -} - -func TestNumeric(t *testing.T) { - valid := Validation{} - - if valid.Numeric("a,1-@ $", "numeric").Ok { - t.Error("\"a,1-@ $\" are valid numeric characters should be false") - } - if !valid.Numeric("1234", "numeric").Ok { - t.Error("\"1234\" are valid numeric characters should be true") - } -} - -func TestAlphaNumeric(t *testing.T) { - valid := Validation{} - - if valid.AlphaNumeric("a,1-@ $", "alphaNumeric").Ok { - t.Error("\"a,1-@ $\" are valid alpha or numeric characters should be false") - } - if !valid.AlphaNumeric("1234aB", "alphaNumeric").Ok { - t.Error("\"1234aB\" are valid alpha or numeric characters should be true") - } -} - -const email = "suchuangji@gmail.com" - -func TestMatch(t *testing.T) { - valid := Validation{} - - if valid.Match("suchuangji@gmail", regexp.MustCompile(`^\w+@\w+\.\w+$`), "match").Ok { - t.Error("\"suchuangji@gmail\" match \"^\\w+@\\w+\\.\\w+$\" should be false") - } - - if !valid.Match(email, regexp.MustCompile(`^\w+@\w+\.\w+$`), "match").Ok { - t.Error("\"suchuangji@gmail\" match \"^\\w+@\\w+\\.\\w+$\" should be true") - } -} - -func TestNoMatch(t *testing.T) { - valid := Validation{} - - if valid.NoMatch("123@gmail", regexp.MustCompile(`[^\w\d]`), "nomatch").Ok { - t.Error("\"123@gmail\" not match \"[^\\w\\d]\" should be false") - } - if !valid.NoMatch("123gmail", regexp.MustCompile(`[^\w\d]`), "match").Ok { - t.Error("\"123@gmail\" not match \"[^\\w\\d@]\" should be true") - } -} - -func TestAlphaDash(t *testing.T) { - valid := Validation{} - - if valid.AlphaDash("a,1-@ $", "alphaDash").Ok { - t.Error("\"a,1-@ $\" are valid alpha or numeric or dash(-_) characters should be false") - } - if !valid.AlphaDash("1234aB-_", "alphaDash").Ok { - t.Error("\"1234aB\" are valid alpha or numeric or dash(-_) characters should be true") - } -} - -func TestEmail(t *testing.T) { - valid := Validation{} - - if valid.Email("not@a email", "email").Ok { - t.Error("\"not@a email\" is a valid email address should be false") - } - if !valid.Email(email, "email").Ok { - t.Error("\"suchuangji@gmail.com\" is a valid email address should be true") - } - if valid.Email("@suchuangji@gmail.com", "email").Ok { - t.Error("\"@suchuangji@gmail.com\" is a valid email address should be false") - } - if valid.Email("suchuangji@gmail.com ok", "email").Ok { - t.Error("\"suchuangji@gmail.com ok\" is a valid email address should be false") - } -} - -func TestIP(t *testing.T) { - valid := Validation{} - - if valid.IP("11.255.255.256", "IP").Ok { - t.Error("\"11.255.255.256\" is a valid ip address should be false") - } - if !valid.IP("01.11.11.11", "IP").Ok { - t.Error("\"suchuangji@gmail.com\" is a valid ip address should be true") - } -} - -func TestBase64(t *testing.T) { - valid := Validation{} - - if valid.Base64(email, "base64").Ok { - t.Error("\"suchuangji@gmail.com\" are a valid base64 characters should be false") - } - if !valid.Base64("c3VjaHVhbmdqaUBnbWFpbC5jb20=", "base64").Ok { - t.Error("\"c3VjaHVhbmdqaUBnbWFpbC5jb20=\" are a valid base64 characters should be true") - } -} - -func TestMobile(t *testing.T) { - valid := Validation{} - - validMobiles := []string{ - "19800008888", - "18800008888", - "18000008888", - "8618300008888", - "+8614700008888", - "17300008888", - "+8617100008888", - "8617500008888", - "8617400008888", - "16200008888", - "16500008888", - "16600008888", - "16700008888", - "13300008888", - "14900008888", - "15300008888", - "17300008888", - "17700008888", - "18000008888", - "18900008888", - "19100008888", - "19900008888", - "19300008888", - "13000008888", - "13100008888", - "13200008888", - "14500008888", - "15500008888", - "15600008888", - "16600008888", - "17100008888", - "17500008888", - "17600008888", - "18500008888", - "18600008888", - "13400008888", - "13500008888", - "13600008888", - "13700008888", - "13800008888", - "13900008888", - "14700008888", - "15000008888", - "15100008888", - "15200008888", - "15800008888", - "15900008888", - "17200008888", - "17800008888", - "18200008888", - "18300008888", - "18400008888", - "18700008888", - "18800008888", - "19800008888", - } - - for _, m := range validMobiles { - if !valid.Mobile(m, "mobile").Ok { - t.Error(m + " is a valid mobile phone number should be true") - } - } -} - -func TestTel(t *testing.T) { - valid := Validation{} - - if valid.Tel("222-00008888", "telephone").Ok { - t.Error("\"222-00008888\" is a valid telephone number should be false") - } - if !valid.Tel("022-70008888", "telephone").Ok { - t.Error("\"022-70008888\" is a valid telephone number should be true") - } - if !valid.Tel("02270008888", "telephone").Ok { - t.Error("\"02270008888\" is a valid telephone number should be true") - } - if !valid.Tel("70008888", "telephone").Ok { - t.Error("\"70008888\" is a valid telephone number should be true") - } -} - -func TestPhone(t *testing.T) { - valid := Validation{} - - if valid.Phone("222-00008888", "phone").Ok { - t.Error("\"222-00008888\" is a valid phone number should be false") - } - if !valid.Mobile("+8614700008888", "phone").Ok { - t.Error("\"+8614700008888\" is a valid phone number should be true") - } - if !valid.Tel("02270008888", "phone").Ok { - t.Error("\"02270008888\" is a valid phone number should be true") - } -} - -func TestZipCode(t *testing.T) { - valid := Validation{} - - if valid.ZipCode("", "zipcode").Ok { - t.Error("\"00008888\" is a valid zipcode should be false") - } - if !valid.ZipCode("536000", "zipcode").Ok { - t.Error("\"536000\" is a valid zipcode should be true") - } -} - -func TestValid(t *testing.T) { - type user struct { - ID int - Name string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"` - Age int `valid:"Required;Range(1, 140)"` - } - valid := Validation{} - - u := user{Name: "test@/test/;com", Age: 40} - b, err := valid.Valid(u) - assert.Nil(t, err) - assert.True(t, b) - - uptr := &user{Name: "test", Age: 40} - valid.Clear() - b, err = valid.Valid(uptr) - - assert.Nil(t, err) - assert.False(t, b) - assert.Equal(t, 1, len(valid.Errors)) - assert.Equal(t, "Name.Match", valid.Errors[0].Key) - - u = user{Name: "test@/test/;com", Age: 180} - valid.Clear() - b, err = valid.Valid(u) - assert.Nil(t, err) - assert.False(t, b) - assert.Equal(t, 1, len(valid.Errors)) - assert.Equal(t, "Age.Range.", valid.Errors[0].Key) -} - -func TestRecursiveValid(t *testing.T) { - type User struct { - ID int - Name string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"` - Age int `valid:"Required;Range(1, 140)"` - } - - type AnonymouseUser struct { - ID2 int - Name2 string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"` - Age2 int `valid:"Required;Range(1, 140)"` - } - - type Account struct { - Password string `valid:"Required"` - U User - AnonymouseUser - } - valid := Validation{} - - u := Account{Password: "abc123_", U: User{}} - b, err := valid.RecursiveValid(u) - assert.Nil(t, err) - assert.False(t, b) -} - -func TestSkipValid(t *testing.T) { - type User struct { - ID int - - Email string `valid:"Email"` - ReqEmail string `valid:"Required;Email"` - - IP string `valid:"IP"` - ReqIP string `valid:"Required;IP"` - - Mobile string `valid:"Mobile"` - ReqMobile string `valid:"Required;Mobile"` - - Tel string `valid:"Tel"` - ReqTel string `valid:"Required;Tel"` - - Phone string `valid:"Phone"` - ReqPhone string `valid:"Required;Phone"` - - ZipCode string `valid:"ZipCode"` - ReqZipCode string `valid:"Required;ZipCode"` - } - - u := User{ - ReqEmail: "a@a.com", - ReqIP: "127.0.0.1", - ReqMobile: "18888888888", - ReqTel: "02088888888", - ReqPhone: "02088888888", - ReqZipCode: "510000", - } - - valid := Validation{} - b, err := valid.Valid(u) - assert.Nil(t, err) - assert.False(t, b) - - valid = Validation{RequiredFirst: true} - b, err = valid.Valid(u) - assert.Nil(t, err) - assert.True(t, b) -} - -func TestPointer(t *testing.T) { - type User struct { - ID int - - Email *string `valid:"Email"` - ReqEmail *string `valid:"Required;Email"` - } - - u := User{ - ReqEmail: nil, - Email: nil, - } - - valid := Validation{} - b, err := valid.Valid(u) - assert.Nil(t, err) - assert.False(t, b) - - validEmail := "a@a.com" - u = User{ - ReqEmail: &validEmail, - Email: nil, - } - - valid = Validation{RequiredFirst: true} - b, err = valid.Valid(u) - assert.Nil(t, err) - assert.True(t, b) - - u = User{ - ReqEmail: &validEmail, - Email: nil, - } - - valid = Validation{} - b, err = valid.Valid(u) - assert.Nil(t, err) - assert.False(t, b) - - invalidEmail := "a@a" - u = User{ - ReqEmail: &validEmail, - Email: &invalidEmail, - } - - valid = Validation{RequiredFirst: true} - b, err = valid.Valid(u) - assert.Nil(t, err) - assert.False(t, b) - - u = User{ - ReqEmail: &validEmail, - Email: &invalidEmail, - } - - valid = Validation{} - b, err = valid.Valid(u) - assert.Nil(t, err) - assert.False(t, b) -} - -func TestCanSkipAlso(t *testing.T) { - type User struct { - ID int - - Email string `valid:"Email"` - ReqEmail string `valid:"Required;Email"` - MatchRange int `valid:"Range(10, 20)"` - } - - u := User{ - ReqEmail: "a@a.com", - Email: "", - MatchRange: 0, - } - - valid := Validation{RequiredFirst: true} - b, err := valid.Valid(u) - assert.Nil(t, err) - assert.False(t, b) - - valid = Validation{RequiredFirst: true} - valid.CanSkipAlso("Range") - b, err = valid.Valid(u) - - assert.Nil(t, err) - assert.True(t, b) -} diff --git a/adapter/validation/validators.go b/adapter/validation/validators.go deleted file mode 100644 index f4d7db3b..00000000 --- a/adapter/validation/validators.go +++ /dev/null @@ -1,512 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package validation - -import ( - "sync" - - "github.com/beego/beego/v2/core/validation" -) - -// CanSkipFuncs will skip valid if RequiredFirst is true and the struct field's value is empty -var CanSkipFuncs = validation.CanSkipFuncs - -// MessageTmpls store commond validate template -var MessageTmpls = map[string]string{ - "Required": "Can not be empty", - "Min": "Minimum is %d", - "Max": "Maximum is %d", - "Range": "Range is %d to %d", - "MinSize": "Minimum size is %d", - "MaxSize": "Maximum size is %d", - "Length": "Required length is %d", - "Alpha": "Must be valid alpha characters", - "Numeric": "Must be valid numeric characters", - "AlphaNumeric": "Must be valid alpha or numeric characters", - "Match": "Must match %s", - "NoMatch": "Must not match %s", - "AlphaDash": "Must be valid alpha or numeric or dash(-_) characters", - "Email": "Must be a valid email address", - "IP": "Must be a valid ip address", - "Base64": "Must be valid base64 characters", - "Mobile": "Must be valid mobile number", - "Tel": "Must be valid telephone number", - "Phone": "Must be valid telephone or mobile phone number", - "ZipCode": "Must be valid zipcode", -} - -var once sync.Once - -// SetDefaultMessage set default messages -// if not set, the default messages are -// "Required": "Can not be empty", -// "Min": "Minimum is %d", -// "Max": "Maximum is %d", -// "Range": "Range is %d to %d", -// "MinSize": "Minimum size is %d", -// "MaxSize": "Maximum size is %d", -// "Length": "Required length is %d", -// "Alpha": "Must be valid alpha characters", -// "Numeric": "Must be valid numeric characters", -// "AlphaNumeric": "Must be valid alpha or numeric characters", -// "Match": "Must match %s", -// "NoMatch": "Must not match %s", -// "AlphaDash": "Must be valid alpha or numeric or dash(-_) characters", -// "Email": "Must be a valid email address", -// "IP": "Must be a valid ip address", -// "Base64": "Must be valid base64 characters", -// "Mobile": "Must be valid mobile number", -// "Tel": "Must be valid telephone number", -// "Phone": "Must be valid telephone or mobile phone number", -// "ZipCode": "Must be valid zipcode", -func SetDefaultMessage(msg map[string]string) { - validation.SetDefaultMessage(msg) -} - -// Validator interface -type Validator interface { - IsSatisfied(interface{}) bool - DefaultMessage() string - GetKey() string - GetLimitValue() interface{} -} - -// Required struct -type Required validation.Required - -// IsSatisfied judge whether obj has value -func (r Required) IsSatisfied(obj interface{}) bool { - return validation.Required(r).IsSatisfied(obj) -} - -// DefaultMessage return the default error message -func (r Required) DefaultMessage() string { - return validation.Required(r).DefaultMessage() -} - -// GetKey return the r.Key -func (r Required) GetKey() string { - return validation.Required(r).GetKey() -} - -// GetLimitValue return nil now -func (r Required) GetLimitValue() interface{} { - return validation.Required(r).GetLimitValue() -} - -// Min check struct -type Min validation.Min - -// IsSatisfied judge whether obj is valid -// not support int64 on 32-bit platform -func (m Min) IsSatisfied(obj interface{}) bool { - return validation.Min(m).IsSatisfied(obj) -} - -// DefaultMessage return the default min error message -func (m Min) DefaultMessage() string { - return validation.Min(m).DefaultMessage() -} - -// GetKey return the m.Key -func (m Min) GetKey() string { - return validation.Min(m).GetKey() -} - -// GetLimitValue return the limit value, Min -func (m Min) GetLimitValue() interface{} { - return validation.Min(m).GetLimitValue() -} - -// Max validate struct -type Max validation.Max - -// IsSatisfied judge whether obj is valid -// not support int64 on 32-bit platform -func (m Max) IsSatisfied(obj interface{}) bool { - return validation.Max(m).IsSatisfied(obj) -} - -// DefaultMessage return the default max error message -func (m Max) DefaultMessage() string { - return validation.Max(m).DefaultMessage() -} - -// GetKey return the m.Key -func (m Max) GetKey() string { - return validation.Max(m).GetKey() -} - -// GetLimitValue return the limit value, Max -func (m Max) GetLimitValue() interface{} { - return validation.Max(m).GetLimitValue() -} - -// Range Requires an integer to be within Min, Max inclusive. -type Range validation.Range - -// IsSatisfied judge whether obj is valid -// not support int64 on 32-bit platform -func (r Range) IsSatisfied(obj interface{}) bool { - return validation.Range(r).IsSatisfied(obj) -} - -// DefaultMessage return the default Range error message -func (r Range) DefaultMessage() string { - return validation.Range(r).DefaultMessage() -} - -// GetKey return the m.Key -func (r Range) GetKey() string { - return validation.Range(r).GetKey() -} - -// GetLimitValue return the limit value, Max -func (r Range) GetLimitValue() interface{} { - return validation.Range(r).GetLimitValue() -} - -// MinSize Requires an array or string to be at least a given length. -type MinSize validation.MinSize - -// IsSatisfied judge whether obj is valid -func (m MinSize) IsSatisfied(obj interface{}) bool { - return validation.MinSize(m).IsSatisfied(obj) -} - -// DefaultMessage return the default MinSize error message -func (m MinSize) DefaultMessage() string { - return validation.MinSize(m).DefaultMessage() -} - -// GetKey return the m.Key -func (m MinSize) GetKey() string { - return validation.MinSize(m).GetKey() -} - -// GetLimitValue return the limit value -func (m MinSize) GetLimitValue() interface{} { - return validation.MinSize(m).GetLimitValue() -} - -// MaxSize Requires an array or string to be at most a given length. -type MaxSize validation.MaxSize - -// IsSatisfied judge whether obj is valid -func (m MaxSize) IsSatisfied(obj interface{}) bool { - return validation.MaxSize(m).IsSatisfied(obj) -} - -// DefaultMessage return the default MaxSize error message -func (m MaxSize) DefaultMessage() string { - return validation.MaxSize(m).DefaultMessage() -} - -// GetKey return the m.Key -func (m MaxSize) GetKey() string { - return validation.MaxSize(m).GetKey() -} - -// GetLimitValue return the limit value -func (m MaxSize) GetLimitValue() interface{} { - return validation.MaxSize(m).GetLimitValue() -} - -// Length Requires an array or string to be exactly a given length. -type Length validation.Length - -// IsSatisfied judge whether obj is valid -func (l Length) IsSatisfied(obj interface{}) bool { - return validation.Length(l).IsSatisfied(obj) -} - -// DefaultMessage return the default Length error message -func (l Length) DefaultMessage() string { - return validation.Length(l).DefaultMessage() -} - -// GetKey return the m.Key -func (l Length) GetKey() string { - return validation.Length(l).GetKey() -} - -// GetLimitValue return the limit value -func (l Length) GetLimitValue() interface{} { - return validation.Length(l).GetLimitValue() -} - -// Alpha check the alpha -type Alpha validation.Alpha - -// IsSatisfied judge whether obj is valid -func (a Alpha) IsSatisfied(obj interface{}) bool { - return validation.Alpha(a).IsSatisfied(obj) -} - -// DefaultMessage return the default Length error message -func (a Alpha) DefaultMessage() string { - return validation.Alpha(a).DefaultMessage() -} - -// GetKey return the m.Key -func (a Alpha) GetKey() string { - return validation.Alpha(a).GetKey() -} - -// GetLimitValue return the limit value -func (a Alpha) GetLimitValue() interface{} { - return validation.Alpha(a).GetLimitValue() -} - -// Numeric check number -type Numeric validation.Numeric - -// IsSatisfied judge whether obj is valid -func (n Numeric) IsSatisfied(obj interface{}) bool { - return validation.Numeric(n).IsSatisfied(obj) -} - -// DefaultMessage return the default Length error message -func (n Numeric) DefaultMessage() string { - return validation.Numeric(n).DefaultMessage() -} - -// GetKey return the n.Key -func (n Numeric) GetKey() string { - return validation.Numeric(n).GetKey() -} - -// GetLimitValue return the limit value -func (n Numeric) GetLimitValue() interface{} { - return validation.Numeric(n).GetLimitValue() -} - -// AlphaNumeric check alpha and number -type AlphaNumeric validation.AlphaNumeric - -// IsSatisfied judge whether obj is valid -func (a AlphaNumeric) IsSatisfied(obj interface{}) bool { - return validation.AlphaNumeric(a).IsSatisfied(obj) -} - -// DefaultMessage return the default Length error message -func (a AlphaNumeric) DefaultMessage() string { - return validation.AlphaNumeric(a).DefaultMessage() -} - -// GetKey return the a.Key -func (a AlphaNumeric) GetKey() string { - return validation.AlphaNumeric(a).GetKey() -} - -// GetLimitValue return the limit value -func (a AlphaNumeric) GetLimitValue() interface{} { - return validation.AlphaNumeric(a).GetLimitValue() -} - -// Match Requires a string to match a given regex. -type Match validation.Match - -// IsSatisfied judge whether obj is valid -func (m Match) IsSatisfied(obj interface{}) bool { - return validation.Match(m).IsSatisfied(obj) -} - -// DefaultMessage return the default Match error message -func (m Match) DefaultMessage() string { - return validation.Match(m).DefaultMessage() -} - -// GetKey return the m.Key -func (m Match) GetKey() string { - return validation.Match(m).GetKey() -} - -// GetLimitValue return the limit value -func (m Match) GetLimitValue() interface{} { - return validation.Match(m).GetLimitValue() -} - -// NoMatch Requires a string to not match a given regex. -type NoMatch validation.NoMatch - -// IsSatisfied judge whether obj is valid -func (n NoMatch) IsSatisfied(obj interface{}) bool { - return validation.NoMatch(n).IsSatisfied(obj) -} - -// DefaultMessage return the default NoMatch error message -func (n NoMatch) DefaultMessage() string { - return validation.NoMatch(n).DefaultMessage() -} - -// GetKey return the n.Key -func (n NoMatch) GetKey() string { - return validation.NoMatch(n).GetKey() -} - -// GetLimitValue return the limit value -func (n NoMatch) GetLimitValue() interface{} { - return validation.NoMatch(n).GetLimitValue() -} - -// AlphaDash check not Alpha -type AlphaDash validation.AlphaDash - -// DefaultMessage return the default AlphaDash error message -func (a AlphaDash) DefaultMessage() string { - return validation.AlphaDash(a).DefaultMessage() -} - -// GetKey return the n.Key -func (a AlphaDash) GetKey() string { - return validation.AlphaDash(a).GetKey() -} - -// GetLimitValue return the limit value -func (a AlphaDash) GetLimitValue() interface{} { - return validation.AlphaDash(a).GetLimitValue() -} - -// Email check struct -type Email validation.Email - -// DefaultMessage return the default Email error message -func (e Email) DefaultMessage() string { - return validation.Email(e).DefaultMessage() -} - -// GetKey return the n.Key -func (e Email) GetKey() string { - return validation.Email(e).GetKey() -} - -// GetLimitValue return the limit value -func (e Email) GetLimitValue() interface{} { - return validation.Email(e).GetLimitValue() -} - -// IP check struct -type IP validation.IP - -// DefaultMessage return the default IP error message -func (i IP) DefaultMessage() string { - return validation.IP(i).DefaultMessage() -} - -// GetKey return the i.Key -func (i IP) GetKey() string { - return validation.IP(i).GetKey() -} - -// GetLimitValue return the limit value -func (i IP) GetLimitValue() interface{} { - return validation.IP(i).GetLimitValue() -} - -// Base64 check struct -type Base64 validation.Base64 - -// DefaultMessage return the default Base64 error message -func (b Base64) DefaultMessage() string { - return validation.Base64(b).DefaultMessage() -} - -// GetKey return the b.Key -func (b Base64) GetKey() string { - return validation.Base64(b).GetKey() -} - -// GetLimitValue return the limit value -func (b Base64) GetLimitValue() interface{} { - return validation.Base64(b).GetLimitValue() -} - -// Mobile check struct -type Mobile validation.Mobile - -// DefaultMessage return the default Mobile error message -func (m Mobile) DefaultMessage() string { - return validation.Mobile(m).DefaultMessage() -} - -// GetKey return the m.Key -func (m Mobile) GetKey() string { - return validation.Mobile(m).GetKey() -} - -// GetLimitValue return the limit value -func (m Mobile) GetLimitValue() interface{} { - return validation.Mobile(m).GetLimitValue() -} - -// Tel check telephone struct -type Tel validation.Tel - -// DefaultMessage return the default Tel error message -func (t Tel) DefaultMessage() string { - return validation.Tel(t).DefaultMessage() -} - -// GetKey return the t.Key -func (t Tel) GetKey() string { - return validation.Tel(t).GetKey() -} - -// GetLimitValue return the limit value -func (t Tel) GetLimitValue() interface{} { - return validation.Tel(t).GetLimitValue() -} - -// Phone just for chinese telephone or mobile phone number -type Phone validation.Phone - -// IsSatisfied judge whether obj is valid -func (p Phone) IsSatisfied(obj interface{}) bool { - return validation.Phone(p).IsSatisfied(obj) -} - -// DefaultMessage return the default Phone error message -func (p Phone) DefaultMessage() string { - return validation.Phone(p).DefaultMessage() -} - -// GetKey return the p.Key -func (p Phone) GetKey() string { - return validation.Phone(p).GetKey() -} - -// GetLimitValue return the limit value -func (p Phone) GetLimitValue() interface{} { - return validation.Phone(p).GetLimitValue() -} - -// ZipCode check the zip struct -type ZipCode validation.ZipCode - -// DefaultMessage return the default Zip error message -func (z ZipCode) DefaultMessage() string { - return validation.ZipCode(z).DefaultMessage() -} - -// GetKey return the z.Key -func (z ZipCode) GetKey() string { - return validation.ZipCode(z).GetKey() -} - -// GetLimitValue return the limit value -func (z ZipCode) GetLimitValue() interface{} { - return validation.ZipCode(z).GetLimitValue() -} diff --git a/client/cache/bloom_filter_cache_test.go b/client/cache/bloom_filter_cache_test.go index ad15f2b4..d26d27cc 100644 --- a/client/cache/bloom_filter_cache_test.go +++ b/client/cache/bloom_filter_cache_test.go @@ -23,9 +23,10 @@ import ( "testing" "time" - "github.com/beego/beego/v2/core/berror" "github.com/bits-and-blooms/bloom/v3" "github.com/stretchr/testify/assert" + + "github.com/beego/beego/v2/core/berror" ) type MockDB struct { diff --git a/client/cache/cache.go b/client/cache/cache.go index 8710643a..f7599dbb 100644 --- a/client/cache/cache.go +++ b/client/cache/cache.go @@ -16,7 +16,9 @@ // Usage: // // import( -// "github.com/beego/beego/v2/client/cache" +// +// "github.com/beego/beego/v2/client/cache" +// // ) // // bm, err := cache.NewCache("memory", `{"interval":60}`) @@ -27,7 +29,6 @@ // bm.Get("astaxie") // bm.IsExist("astaxie") // bm.Delete("astaxie") -// package cache import ( @@ -39,6 +40,7 @@ import ( // Cache interface contains all behaviors for cache adapter. // usage: +// // cache.Register("file",cache.NewFileCache) // this operation is run in init method of file.go. // c,err := cache.NewCache("file","{....}") // c.Put("key",value, 3600 * time.Second) diff --git a/client/cache/error_code.go b/client/cache/error_code.go index 74e387a1..2aa9ffc8 100644 --- a/client/cache/error_code.go +++ b/client/cache/error_code.go @@ -189,6 +189,10 @@ The response from SSDB server is invalid. Usually it indicates something wrong on server side. `) +var DeleteFailed = berror.DefineCode(5002008, moduleName, "DeleteFailed", ` +Beego attempt to delete cache item failed. Please check if the target key is correct. +`) + var ( ErrKeyExpired = berror.Error(KeyExpired, "the key is expired") ErrKeyNotExist = berror.Error(KeyNotExist, "the key isn't exist") diff --git a/client/cache/file.go b/client/cache/file.go index 172c568e..d2b4a774 100644 --- a/client/cache/file.go +++ b/client/cache/file.go @@ -23,7 +23,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "os" "path/filepath" "strconv" @@ -295,7 +294,7 @@ func exists(path string) (bool, error) { // FileGetContents Reads bytes from a file. // if non-existent, create this file. func FileGetContents(filename string) ([]byte, error) { - data, err := ioutil.ReadFile(filename) + data, err := os.ReadFile(filename) if err != nil { return nil, berror.Wrapf(err, ReadFileCacheContentFailed, "could not read the data from the file: %s, "+ @@ -307,7 +306,7 @@ func FileGetContents(filename string) ([]byte, error) { // FilePutContents puts bytes into a file. // if non-existent, create this file. func FilePutContents(filename string, content []byte) error { - return ioutil.WriteFile(filename, content, os.ModePerm) + return os.WriteFile(filename, content, os.ModePerm) } // GobEncode Gob encodes a file cache item. diff --git a/client/cache/memcache/memcache.go b/client/cache/memcache/memcache.go index ad645f07..4c6cf0dd 100644 --- a/client/cache/memcache/memcache.go +++ b/client/cache/memcache/memcache.go @@ -20,12 +20,13 @@ // // Usage: // import( -// _ "github.com/beego/beego/v2/client/cache/memcache" -// "github.com/beego/beego/v2/client/cache" +// +// _ "github.com/beego/beego/v2/client/cache/memcache" +// "github.com/beego/beego/v2/client/cache" +// // ) // -// bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`) -// +// bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`) package memcache import ( diff --git a/client/cache/redis/redis.go b/client/cache/redis/redis.go index 4d891a80..c2b2eaa8 100644 --- a/client/cache/redis/redis.go +++ b/client/cache/redis/redis.go @@ -20,12 +20,13 @@ // // Usage: // import( -// _ "github.com/beego/beego/v2/client/cache/redis" -// "github.com/beego/beego/v2/client/cache" +// +// _ "github.com/beego/beego/v2/client/cache/redis" +// "github.com/beego/beego/v2/client/cache" +// // ) // -// bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`) -// +// bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`) package redis import ( @@ -42,19 +43,32 @@ import ( "github.com/beego/beego/v2/core/berror" ) -// DefaultKey defines the collection name of redis for the cache adapter. -var DefaultKey = "beecacheRedis" +const ( + // DefaultKey defines the collection name of redis for the cache adapter. + DefaultKey = "beecacheRedis" + // defaultMaxIdle defines the default max idle connection number. + defaultMaxIdle = 3 + // defaultTimeout defines the default timeout . + defaultTimeout = time.Second * 180 +) // Cache is Redis cache adapter. type Cache struct { p *redis.Pool // redis connection pool conninfo string dbNum int + // key actually is prefix. key string password string maxIdle int - // Timeout value (less than the redis server's timeout value) + // skipEmptyPrefix for backward compatible, + // check function associate + // see https://github.com/beego/beego/issues/5248 + skipEmptyPrefix bool + + // Timeout value (less than the redis server's timeout value). + // Timeout used for idle connection timeout time.Duration } @@ -82,6 +96,9 @@ func (rc *Cache) do(commandName string, args ...interface{}) (interface{}, error // associate with config key. func (rc *Cache) associate(originKey interface{}) string { + if rc.key == "" && rc.skipEmptyPrefix { + return fmt.Sprintf("%s", originKey) + } return fmt.Sprintf("%s:%s", rc.key, originKey) } @@ -191,51 +208,12 @@ func (rc *Cache) Scan(pattern string) (keys []string, err error) { } // StartAndGC starts the redis cache adapter. -// config: must be in this format {"key":"collection key","conn":"connection info","dbNum":"0"} +// config: must be in this format {"key":"collection key","conn":"connection info","dbNum":"0", "skipEmptyPrefix":"true"} // Cached items in redis are stored forever, no garbage collection happens func (rc *Cache) StartAndGC(config string) error { - var cf map[string]string - err := json.Unmarshal([]byte(config), &cf) + err := rc.parseConf(config) if err != nil { - return berror.Wrapf(err, cache.InvalidRedisCacheCfg, "could not unmarshal the config: %s", config) - } - - if _, ok := cf["key"]; !ok { - cf["key"] = DefaultKey - } - if _, ok := cf["conn"]; !ok { - return berror.Wrapf(err, cache.InvalidRedisCacheCfg, "config missing conn field: %s", config) - } - - // Format redis://@: - cf["conn"] = strings.Replace(cf["conn"], "redis://", "", 1) - if i := strings.Index(cf["conn"], "@"); i > -1 { - cf["password"] = cf["conn"][0:i] - cf["conn"] = cf["conn"][i+1:] - } - - if _, ok := cf["dbNum"]; !ok { - cf["dbNum"] = "0" - } - if _, ok := cf["password"]; !ok { - cf["password"] = "" - } - if _, ok := cf["maxIdle"]; !ok { - cf["maxIdle"] = "3" - } - if _, ok := cf["timeout"]; !ok { - cf["timeout"] = "180s" - } - rc.key = cf["key"] - rc.conninfo = cf["conn"] - rc.dbNum, _ = strconv.Atoi(cf["dbNum"]) - rc.password = cf["password"] - rc.maxIdle, _ = strconv.Atoi(cf["maxIdle"]) - - if v, err := time.ParseDuration(cf["timeout"]); err == nil { - rc.timeout = v - } else { - rc.timeout = 180 * time.Second + return err } rc.connectInit() @@ -253,6 +231,89 @@ func (rc *Cache) StartAndGC(config string) error { return nil } +func (rc *Cache) parseConf(config string) error { + var cf redisConfig + err := json.Unmarshal([]byte(config), &cf) + if err != nil { + return berror.Wrapf(err, cache.InvalidRedisCacheCfg, "could not unmarshal the config: %s", config) + } + + err = cf.parse() + if err != nil { + return err + } + + rc.dbNum = cf.dbNum + rc.key = cf.Key + rc.conninfo = cf.Conn + rc.password = cf.password + rc.maxIdle = cf.maxIdle + rc.timeout = cf.timeout + rc.skipEmptyPrefix = cf.skipEmptyPrefix + + return nil +} + +type redisConfig struct { + DbNum string `json:"dbNum"` + SkipEmptyPrefix string `json:"skipEmptyPrefix"` + Key string `json:"key"` + // Format redis://@: + Conn string `json:"conn"` + MaxIdle string `json:"maxIdle"` + TimeoutStr string `json:"timeout"` + + dbNum int + skipEmptyPrefix bool + maxIdle int + // parse from Conn + password string + // timeout used for idle connection, default is 180 seconds. + timeout time.Duration +} + +// parse parses the config. +// If the necessary settings have not been set, it will return an error. +// It will fill the default values if some fields are missing. +func (cf *redisConfig) parse() error { + if cf.Conn == "" { + return berror.Error(cache.InvalidRedisCacheCfg, "config missing conn field") + } + + // Format redis://@: + cf.Conn = strings.Replace(cf.Conn, "redis://", "", 1) + if i := strings.Index(cf.Conn, "@"); i > -1 { + cf.password = cf.Conn[0:i] + cf.Conn = cf.Conn[i+1:] + } + + if cf.Key == "" { + cf.Key = DefaultKey + } + + if cf.DbNum != "" { + cf.dbNum, _ = strconv.Atoi(cf.DbNum) + } + + if cf.SkipEmptyPrefix != "" { + cf.skipEmptyPrefix, _ = strconv.ParseBool(cf.SkipEmptyPrefix) + } + + if cf.MaxIdle == "" { + cf.maxIdle = defaultMaxIdle + } else { + cf.maxIdle, _ = strconv.Atoi(cf.MaxIdle) + } + + if v, err := time.ParseDuration(cf.TimeoutStr); err == nil { + cf.timeout = v + } else { + cf.timeout = defaultTimeout + } + + return nil +} + // connect to redis. func (rc *Cache) connectInit() { dialFunc := func() (c redis.Conn, err error) { diff --git a/client/cache/redis/redis_test.go b/client/cache/redis/redis_test.go index 138ccc2c..d70f1817 100644 --- a/client/cache/redis/redis_test.go +++ b/client/cache/redis/redis_test.go @@ -248,3 +248,114 @@ func (m *MockOrm) Load(key string) (any, error) { } return m.kvs[key], nil } + +func TestCache_associate(t *testing.T) { + testCases := []struct { + name string + skipEmptyPrefix bool + prefix string + input string + wantRes string + }{ + { + name: "skip prefix", + skipEmptyPrefix: true, + prefix: "", + input: "my-key", + wantRes: "my-key", + }, + { + name: "skip prefix but prefix not empty", + skipEmptyPrefix: true, + prefix: "abc", + input: "my-key", + wantRes: "abc:my-key", + }, + { + name: "using empty prefix", + skipEmptyPrefix: false, + prefix: "", + input: "my-key", + wantRes: ":my-key", + }, + { + name: "using prefix", + prefix: "abc", + input: "my-key", + wantRes: "abc:my-key", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + c := NewRedisCache().(*Cache) + c.skipEmptyPrefix = tc.skipEmptyPrefix + c.key = tc.prefix + res := c.associate(tc.input) + assert.Equal(t, tc.wantRes, res) + }) + } +} + +func TestCache_parseConf(t *testing.T) { + tests := []struct { + name string + + configStr string + + wantCache Cache + wantErr error + }{ + { + name: "just conn", + configStr: `{ + "conn": "127.0.0.1:6379" +}`, + + wantCache: Cache{ + conninfo: "127.0.0.1:6379", + dbNum: 0, + key: DefaultKey, + password: "", + maxIdle: defaultMaxIdle, + skipEmptyPrefix: false, + timeout: defaultTimeout, + }, + wantErr: nil, + }, + + { + name: "all", + configStr: `{ + "dbNum": "2", + "skipEmptyPrefix": "true", + "key": "mykey", + "conn": "redis://mypwd@127.0.0.1:6379", + "maxIdle": "10", + "timeout": "30s" +}`, + + wantCache: Cache{ + conninfo: "127.0.0.1:6379", + dbNum: 2, + key: "mykey", + password: "mypwd", + maxIdle: 10, + skipEmptyPrefix: true, + timeout: time.Second * 30, + }, + wantErr: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := Cache{} + err := c.parseConf(tt.configStr) + assert.Equal(t, tt.wantErr, err) + if err != nil { + return + } + assert.Equal(t, tt.wantCache, c) + }) + } +} diff --git a/client/cache/write_delete.go b/client/cache/write_delete.go new file mode 100644 index 00000000..a7ed3a1e --- /dev/null +++ b/client/cache/write_delete.go @@ -0,0 +1,96 @@ +// Copyright 2014 beego Author. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cache + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/beego/beego/v2/core/berror" +) + +type WriteDeleteCache struct { + Cache + storeFunc func(ctx context.Context, key string, val any) error +} + +// NewWriteDeleteCache creates a write delete cache pattern decorator. +// The fn is the function that persistent the key and val. +func NewWriteDeleteCache(cache Cache, fn func(ctx context.Context, key string, val any) error) (*WriteDeleteCache, error) { + if fn == nil || cache == nil { + return nil, berror.Error(InvalidInitParameters, "cache or storeFunc can not be nil") + } + + w := &WriteDeleteCache{ + Cache: cache, + storeFunc: fn, + } + return w, nil +} + +func (w *WriteDeleteCache) Set(ctx context.Context, key string, val any) error { + err := w.storeFunc(ctx, key, val) + if err != nil && !errors.Is(err, context.DeadlineExceeded) { + return berror.Wrap(err, PersistCacheFailed, fmt.Sprintf("key: %s, val: %v", key, val)) + } + return w.Cache.Delete(ctx, key) +} + +// WriteDoubleDeleteCache creates write double delete cache pattern decorator. +// The fn is the function that persistent the key and val. +// it will delete the key from cache when you call Set function, and wait for interval, it will delete the key from cache one more time. +// This pattern help to reduce the possibility of data inconsistencies, but it's still possible to be inconsistent among database and cache. +type WriteDoubleDeleteCache struct { + Cache + interval time.Duration + timeout time.Duration + storeFunc func(ctx context.Context, key string, val any) error +} + +type WriteDoubleDeleteCacheOption func(c *WriteDoubleDeleteCache) + +func NewWriteDoubleDeleteCache(cache Cache, interval, timeout time.Duration, + fn func(ctx context.Context, key string, val any) error) (*WriteDoubleDeleteCache, error) { + if fn == nil || cache == nil { + return nil, berror.Error(InvalidInitParameters, "cache or storeFunc can not be nil") + } + + return &WriteDoubleDeleteCache{ + Cache: cache, + interval: interval, + timeout: timeout, + storeFunc: fn, + }, nil +} + +func (c *WriteDoubleDeleteCache) Set( + ctx context.Context, key string, val any) error { + err := c.storeFunc(ctx, key, val) + if err != nil && !errors.Is(err, context.DeadlineExceeded) { + return berror.Wrap(err, PersistCacheFailed, fmt.Sprintf("key: %s, val: %v", key, val)) + } + time.AfterFunc(c.interval, func() { + rCtx, cancel := context.WithTimeout(context.Background(), c.timeout) + _ = c.Cache.Delete(rCtx, key) + cancel() + }) + err = c.Cache.Delete(ctx, key) + if err != nil { + return berror.Wrap(err, DeleteFailed, fmt.Sprintf("write double delete pattern failed to delete the key: %s", key)) + } + return nil +} diff --git a/client/cache/write_delete_test.go b/client/cache/write_delete_test.go new file mode 100644 index 00000000..956f721a --- /dev/null +++ b/client/cache/write_delete_test.go @@ -0,0 +1,393 @@ +// Copyright 2014 beego Author. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// nolint +package cache + +import ( + "context" + "errors" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/stretchr/testify/assert" + + "github.com/beego/beego/v2/core/berror" +) + +func TestWriteDoubleDeleteCache_Set(t *testing.T) { + mockDbStore := make(map[string]any) + + cancels := make([]func(), 0) + defer func() { + for _, cancel := range cancels { + cancel() + } + }() + timeout := time.Second * 3 + testCases := []struct { + name string + cache Cache + storeFunc func(ctx context.Context, key string, val any) error + ctx context.Context + interval time.Duration + sleepSecond time.Duration + key string + value any + wantErr error + }{ + { + name: "store key/value in db fail", + interval: time.Second, + cache: NewMemoryCache(), + storeFunc: func(ctx context.Context, key string, val any) error { + return errors.New("failed") + }, + ctx: context.TODO(), + wantErr: berror.Wrap(errors.New("failed"), PersistCacheFailed, + fmt.Sprintf("key: %s, val: %v", "", nil)), + }, + { + name: "store key/value success", + interval: time.Second * 2, + sleepSecond: time.Second * 3, + cache: func() Cache { + cache := NewMemoryCache() + err := cache.Put(context.Background(), "hello", "world", time.Second*2) + require.NoError(t, err) + return cache + }(), + storeFunc: func(ctx context.Context, key string, val any) error { + mockDbStore[key] = val + return nil + }, + ctx: context.TODO(), + key: "hello", + value: "world", + }, + { + name: "store key/value timeout", + interval: time.Second * 2, + sleepSecond: time.Second * 3, + cache: func() Cache { + cache := NewMemoryCache() + err := cache.Put(context.Background(), "hello", "hello", time.Second*2) + require.NoError(t, err) + return cache + }(), + storeFunc: func(ctx context.Context, key string, val any) error { + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(3 * time.Second): + mockDbStore[key] = val + return nil + } + }, + ctx: func() context.Context { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + cancels = append(cancels, cancel) + return ctx + + }(), + key: "hello", + value: "hello", + }, + } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + cache := tt.cache + c, err := NewWriteDoubleDeleteCache(cache, tt.interval, timeout, tt.storeFunc) + if err != nil { + assert.EqualError(t, tt.wantErr, err.Error()) + return + } + + err = c.Set(tt.ctx, tt.key, tt.value) + if err != nil { + assert.EqualError(t, tt.wantErr, err.Error()) + return + } + + _, err = c.Get(tt.ctx, tt.key) + assert.Equal(t, ErrKeyNotExist, err) + + err = cache.Put(tt.ctx, tt.key, tt.value, tt.interval) + require.NoError(t, err) + + val, err := c.Get(tt.ctx, tt.key) + require.NoError(t, err) + assert.Equal(t, tt.value, val) + + time.Sleep(tt.sleepSecond) + + _, err = c.Get(tt.ctx, tt.key) + assert.Equal(t, ErrKeyNotExist, err) + }) + } +} + +func TestNewWriteDoubleDeleteCache(t *testing.T) { + underlyingCache := NewMemoryCache() + storeFunc := func(ctx context.Context, key string, val any) error { return nil } + + type args struct { + cache Cache + interval time.Duration + fn func(ctx context.Context, key string, val any) error + } + timeout := time.Second * 3 + tests := []struct { + name string + args args + wantRes *WriteDoubleDeleteCache + wantErr error + }{ + { + name: "nil cache parameters", + args: args{ + cache: nil, + fn: storeFunc, + }, + wantErr: berror.Error(InvalidInitParameters, "cache or storeFunc can not be nil"), + }, + { + name: "nil storeFunc parameters", + args: args{ + cache: underlyingCache, + fn: nil, + }, + wantErr: berror.Error(InvalidInitParameters, "cache or storeFunc can not be nil"), + }, + { + name: "init write-though cache success", + args: args{ + cache: underlyingCache, + fn: storeFunc, + interval: time.Second, + }, + wantRes: &WriteDoubleDeleteCache{ + Cache: underlyingCache, + storeFunc: storeFunc, + interval: time.Second, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := NewWriteDoubleDeleteCache(tt.args.cache, tt.args.interval, timeout, tt.args.fn) + assert.Equal(t, tt.wantErr, err) + if err != nil { + return + } + }) + } +} + +func ExampleWriteDoubleDeleteCache() { + c := NewMemoryCache() + wtc, err := NewWriteDoubleDeleteCache(c, 1*time.Second, 3*time.Second, func(ctx context.Context, key string, val any) error { + fmt.Printf("write data to somewhere key %s, val %v \n", key, val) + return nil + }) + if err != nil { + panic(err) + } + err = wtc.Set(context.Background(), + "/biz/user/id=1", "I am user 1") + if err != nil { + panic(err) + } + // Output: + // write data to somewhere key /biz/user/id=1, val I am user 1 +} + +func TestWriteDeleteCache_Set(t *testing.T) { + mockDbStore := make(map[string]any) + + cancels := make([]func(), 0) + defer func() { + for _, cancel := range cancels { + cancel() + } + }() + + testCases := []struct { + name string + cache Cache + storeFunc func(ctx context.Context, key string, val any) error + ctx context.Context + key string + value any + wantErr error + before func(Cache) + after func() + }{ + { + name: "store key/value in db fail", + cache: NewMemoryCache(), + storeFunc: func(ctx context.Context, key string, val any) error { + return errors.New("failed") + }, + ctx: context.TODO(), + wantErr: berror.Wrap(errors.New("failed"), PersistCacheFailed, + fmt.Sprintf("key: %s, val: %v", "", nil)), + before: func(cache Cache) {}, + after: func() {}, + }, + { + name: "store key/value success", + cache: NewMemoryCache(), + storeFunc: func(ctx context.Context, key string, val any) error { + mockDbStore[key] = val + return nil + }, + ctx: context.TODO(), + key: "hello", + value: "world", + before: func(cache Cache) { + _ = cache.Put(context.Background(), "hello", "testVal", 10*time.Second) + }, + after: func() { + delete(mockDbStore, "hello") + }, + }, + { + name: "store key/value timeout", + cache: NewMemoryCache(), + storeFunc: func(ctx context.Context, key string, val any) error { + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(3 * time.Second): + mockDbStore[key] = val + return nil + } + + }, + ctx: func() context.Context { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + cancels = append(cancels, cancel) + return ctx + + }(), + key: "hello", + value: nil, + before: func(cache Cache) { + _ = cache.Put(context.Background(), "hello", "testVal", 10*time.Second) + }, + after: func() {}, + }, + } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + w, err := NewWriteDeleteCache(tt.cache, tt.storeFunc) + if err != nil { + assert.EqualError(t, tt.wantErr, err.Error()) + return + } + + tt.before(tt.cache) + defer func() { + tt.after() + }() + + err = w.Set(tt.ctx, tt.key, tt.value) + if err != nil { + assert.EqualError(t, tt.wantErr, err.Error()) + return + } + + _, err = w.Get(tt.ctx, tt.key) + assert.Equal(t, ErrKeyNotExist, err) + + vv := mockDbStore[tt.key] + assert.Equal(t, tt.value, vv) + }) + } +} + +func TestNewWriteDeleteCache(t *testing.T) { + underlyingCache := NewMemoryCache() + storeFunc := func(ctx context.Context, key string, val any) error { return nil } + + type args struct { + cache Cache + fn func(ctx context.Context, key string, val any) error + } + tests := []struct { + name string + args args + wantRes *WriteDeleteCache + wantErr error + }{ + { + name: "nil cache parameters", + args: args{ + cache: nil, + fn: storeFunc, + }, + wantErr: berror.Error(InvalidInitParameters, "cache or storeFunc can not be nil"), + }, + { + name: "nil storeFunc parameters", + args: args{ + cache: underlyingCache, + fn: nil, + }, + wantErr: berror.Error(InvalidInitParameters, "cache or storeFunc can not be nil"), + }, + { + name: "init write-though cache success", + args: args{ + cache: underlyingCache, + fn: storeFunc, + }, + wantRes: &WriteDeleteCache{ + Cache: underlyingCache, + storeFunc: storeFunc, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := NewWriteDeleteCache(tt.args.cache, tt.args.fn) + assert.Equal(t, tt.wantErr, err) + if err != nil { + return + } + }) + } +} + +func ExampleNewWriteDeleteCache() { + c := NewMemoryCache() + wtc, err := NewWriteDeleteCache(c, func(ctx context.Context, key string, val any) error { + fmt.Printf("write data to somewhere key %s, val %v \n", key, val) + return nil + }) + if err != nil { + panic(err) + } + err = wtc.Set(context.Background(), + "/biz/user/id=1", "I am user 1") + if err != nil { + panic(err) + } + // Output: + // write data to somewhere key /biz/user/id=1, val I am user 1 +} diff --git a/client/httplib/client_option_test.go b/client/httplib/client_option_test.go deleted file mode 100644 index 416f092b..00000000 --- a/client/httplib/client_option_test.go +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2020 beego -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package httplib - -import ( - "errors" - "net" - "net/http" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -type respCarrier struct { - bytes []byte -} - -func (r *respCarrier) SetBytes(bytes []byte) { - r.bytes = bytes -} - -func (r *respCarrier) String() string { - return string(r.bytes) -} - -func TestOptionWithEnableCookie(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/", - WithEnableCookie(true)) - if err != nil { - t.Fatal(err) - } - - v := "smallfish" - resp := &respCarrier{} - err = client.Get(resp, "/cookies/set?k1="+v) - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - err = client.Get(resp, "/cookies") - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), v) - if n == -1 { - t.Fatal(v + " not found in cookie") - } -} - -func TestOptionWithUserAgent(t *testing.T) { - v := "beego" - client, err := NewClient("test", "http://httpbin.org/", - WithUserAgent(v)) - if err != nil { - t.Fatal(err) - } - - resp := &respCarrier{} - err = client.Get(resp, "/headers") - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), v) - if n == -1 { - t.Fatal(v + " not found in user-agent") - } -} - -func TestOptionWithCheckRedirect(t *testing.T) { - client, err := NewClient("test", "https://goolnk.com/33BD2j", - WithCheckRedirect(func(redirectReq *http.Request, redirectVia []*http.Request) error { - return errors.New("Redirect triggered") - })) - if err != nil { - t.Fatal(err) - } - err = client.Get(nil, "") - assert.NotNil(t, err) -} - -func TestOptionWithHTTPSetting(t *testing.T) { - v := "beego" - var setting BeegoHTTPSettings - setting.EnableCookie = true - setting.UserAgent = v - setting.Transport = &http.Transport{ - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, - }).DialContext, - MaxIdleConns: 50, - IdleConnTimeout: 90 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - } - setting.ReadWriteTimeout = 5 * time.Second - - client, err := NewClient("test", "http://httpbin.org/", - WithHTTPSetting(setting)) - if err != nil { - t.Fatal(err) - } - - resp := &respCarrier{} - err = client.Get(resp, "/get") - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), v) - if n == -1 { - t.Fatal(v + " not found in user-agent") - } -} - -func TestOptionWithHeader(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") - if err != nil { - t.Fatal(err) - } - client.CommonOpts = append(client.CommonOpts, WithHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36")) - - resp := &respCarrier{} - err = client.Get(resp, "/headers") - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), "Mozilla/5.0") - if n == -1 { - t.Fatal("Mozilla/5.0 not found in user-agent") - } -} - -func TestOptionWithTokenFactory(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") - if err != nil { - t.Fatal(err) - } - client.CommonOpts = append(client.CommonOpts, - WithTokenFactory(func() string { - return "testauth" - })) - - resp := &respCarrier{} - err = client.Get(resp, "/headers") - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), "testauth") - if n == -1 { - t.Fatal("Auth is not set in request") - } -} - -func TestOptionWithBasicAuth(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") - if err != nil { - t.Fatal(err) - } - - resp := &respCarrier{} - err = client.Get(resp, "/basic-auth/user/passwd", - WithBasicAuth(func() (string, string) { - return "user", "passwd" - })) - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - n := strings.Index(resp.String(), "authenticated") - if n == -1 { - t.Fatal("authenticated not found in response") - } -} - -func TestOptionWithContentType(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") - if err != nil { - t.Fatal(err) - } - - v := "application/json" - resp := &respCarrier{} - err = client.Get(resp, "/headers", WithContentType(v)) - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), v) - if n == -1 { - t.Fatal(v + " not found in header") - } -} - -func TestOptionWithParam(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") - if err != nil { - t.Fatal(err) - } - - v := "smallfish" - resp := &respCarrier{} - err = client.Get(resp, "/get", WithParam("username", v)) - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), v) - if n == -1 { - t.Fatal(v + " not found in header") - } -} - -func TestOptionWithRetry(t *testing.T) { - client, err := NewClient("test", "https://goolnk.com/33BD2j", - WithCheckRedirect(func(redirectReq *http.Request, redirectVia []*http.Request) error { - return errors.New("Redirect triggered") - })) - if err != nil { - t.Fatal(err) - } - - retryAmount := 1 - retryDelay := 800 * time.Millisecond - startTime := time.Now().UnixNano() / int64(time.Millisecond) - - _ = client.Get(nil, "", WithRetry(retryAmount, retryDelay)) - - endTime := time.Now().UnixNano() / int64(time.Millisecond) - elapsedTime := endTime - startTime - delayedTime := int64(retryAmount) * retryDelay.Milliseconds() - if elapsedTime < delayedTime { - t.Errorf("Not enough retries. Took %dms. Delay was meant to take %dms", elapsedTime, delayedTime) - } -} diff --git a/client/httplib/filter/opentracing/filter.go b/client/httplib/filter/opentracing/filter.go index aef20e66..ec212e5b 100644 --- a/client/httplib/filter/opentracing/filter.go +++ b/client/httplib/filter/opentracing/filter.go @@ -18,8 +18,8 @@ import ( "context" "net/http" - logKit "github.com/go-kit/kit/log" opentracingKit "github.com/go-kit/kit/tracing/opentracing" + logKit "github.com/go-kit/log" "github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go/log" diff --git a/client/httplib/http_response.go b/client/httplib/http_response.go index 89930cb1..2f2ca2f8 100644 --- a/client/httplib/http_response.go +++ b/client/httplib/http_response.go @@ -17,7 +17,7 @@ package httplib import ( "bytes" "encoding/json" - "io/ioutil" + "io" "net/http" ) @@ -34,6 +34,6 @@ func NewHttpResponseWithJsonBody(data interface{}) *http.Response { } return &http.Response{ ContentLength: int64(len(body)), - Body: ioutil.NopCloser(bytes.NewReader(body)), + Body: io.NopCloser(bytes.NewReader(body)), } } diff --git a/client/httplib/httpclient.go b/client/httplib/httpclient.go index 524f8bbb..f3ac4afe 100644 --- a/client/httplib/httpclient.go +++ b/client/httplib/httpclient.go @@ -17,7 +17,6 @@ package httplib import ( "bytes" "io" - "io/ioutil" "net/http" ) @@ -105,7 +104,7 @@ func (c *Client) handleCarrier(value interface{}, req *BeegoHTTPRequest) error { if err != nil { return err } - req.resp.Body = ioutil.NopCloser(bytes.NewReader(b)) + req.resp.Body = io.NopCloser(bytes.NewReader(b)) carrier.SetHTTPResponse(req.resp) } if carrier, ok := value.(HTTPBodyCarrier); ok { @@ -113,7 +112,7 @@ func (c *Client) handleCarrier(value interface{}, req *BeegoHTTPRequest) error { if err != nil { return err } - reader := ioutil.NopCloser(bytes.NewReader(b)) + reader := io.NopCloser(bytes.NewReader(b)) carrier.SetReader(reader) } if carrier, ok := value.(HTTPBytesCarrier); ok { diff --git a/client/httplib/httpclient_test.go b/client/httplib/httpclient_test.go index 1ab6d95f..b7dc8769 100644 --- a/client/httplib/httpclient_test.go +++ b/client/httplib/httpclient_test.go @@ -15,12 +15,17 @@ package httplib import ( + "encoding/json" "encoding/xml" "io" - "io/ioutil" + "net" "net/http" "testing" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "gopkg.in/yaml.v3" + "github.com/stretchr/testify/assert" ) @@ -32,13 +37,13 @@ func TestNewClient(t *testing.T) { } type slideShowResponse struct { - Resp *http.Response - bytes []byte - StatusCode int - Body io.ReadCloser - Header map[string][]string + Resp *http.Response `json:"resp,omitempty"` + bytes []byte `json:"bytes,omitempty"` + StatusCode int `json:"status_code,omitempty"` + Body io.ReadCloser `json:"body,omitempty"` + Header map[string][]string `json:"header,omitempty"` - Slideshow slideshow `json:"slideshow" yaml:"slideshow"` + Slideshow slideshow `json:"slideshow,omitempty" yaml:"slideshow" xml:"slideshow"` } func (r *slideShowResponse) SetHTTPResponse(resp *http.Response) { @@ -66,7 +71,7 @@ func (r *slideShowResponse) String() string { } type slideshow struct { - XMLName xml.Name `xml:"slideshow"` + //XMLName xml.Name `xml:"slideshow"` Title string `json:"title" yaml:"title" xml:"title,attr"` Author string `json:"author" yaml:"author" xml:"author,attr"` @@ -80,63 +85,122 @@ type slide struct { Title string `json:"title" yaml:"title" xml:"title"` } -func TestClientHandleCarrier(t *testing.T) { - v := "beego" - client, err := NewClient("test", "http://httpbin.org/", - WithUserAgent(v)) - if err != nil { - t.Fatal(err) - } - - s := &slideShowResponse{} - err = client.Get(s, "/json") - if err != nil { - t.Fatal(err) - } - defer s.Body.Close() - - assert.NotNil(t, s.Resp) - assert.NotNil(t, s.Body) - assert.Equal(t, "429", s.Header["Content-Length"][0]) - assert.Equal(t, 200, s.StatusCode) - - b, err := ioutil.ReadAll(s.Body) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, 429, len(b)) - assert.Equal(t, s.String(), string(b)) +type ClientTestSuite struct { + suite.Suite + l net.Listener } -func TestClientGet(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") +func (c *ClientTestSuite) SetupSuite() { + listener, err := net.Listen("tcp", ":8080") + require.NoError(c.T(), err) + c.l = listener + + handler := http.NewServeMux() + handler.HandleFunc("/json", func(writer http.ResponseWriter, request *http.Request) { + data, _ := json.Marshal(slideshow{}) + _, _ = writer.Write(data) + }) + + ssr := slideShowResponse{ + Slideshow: slideshow{ + Title: "Sample Slide Show", + Slides: []slide{ + { + Title: "Content", + }, + { + Title: "Overview", + }, + }, + }, + } + + handler.HandleFunc("/req2resp", func(writer http.ResponseWriter, request *http.Request) { + data, _ := io.ReadAll(request.Body) + _, _ = writer.Write(data) + }) + + handler.HandleFunc("/get", func(writer http.ResponseWriter, request *http.Request) { + data, _ := json.Marshal(ssr) + _, _ = writer.Write(data) + }) + + handler.HandleFunc("/get/xml", func(writer http.ResponseWriter, request *http.Request) { + data, err := xml.Marshal(ssr.Slideshow) + require.NoError(c.T(), err) + _, _ = writer.Write(data) + }) + + handler.HandleFunc("/get/yaml", func(writer http.ResponseWriter, request *http.Request) { + data, _ := yaml.Marshal(ssr) + _, _ = writer.Write(data) + }) + + go func() { + _ = http.Serve(listener, handler) + }() +} + +func (c *ClientTestSuite) TearDownSuite() { + _ = c.l.Close() +} + +func TestClient(t *testing.T) { + suite.Run(t, &ClientTestSuite{}) +} + +func (c *ClientTestSuite) TestClientHandleCarrier() { + t := c.T() + v := "beego" + client, err := NewClient("test", "http://localhost:8080/", + WithUserAgent(v)) + require.NoError(t, err) + resp := &slideShowResponse{} + err = client.Get(resp, "/json") + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + + assert.NotNil(t, resp.Resp) + assert.NotNil(t, resp.Body) + assert.Equal(t, "48", resp.Header["Content-Length"][0]) + assert.Equal(t, 200, resp.StatusCode) + + b, err := io.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, 48, len(b)) + assert.Equal(t, resp.String(), string(b)) +} + +func (c *ClientTestSuite) TestClientGet() { + t := c.T() + client, err := NewClient("test", "http://localhost:8080/") if err != nil { t.Fatal(err) } // json - var s *slideShowResponse - err = client.Get(&s, "/json") - if err != nil { - t.Fatal(err) - } + var s slideShowResponse + err = client.Get(&s, "/get") + require.NoError(t, err) assert.Equal(t, "Sample Slide Show", s.Slideshow.Title) assert.Equal(t, 2, len(s.Slideshow.Slides)) assert.Equal(t, "Overview", s.Slideshow.Slides[1].Title) // xml - var ssp *slideshow - err = client.Get(&ssp, "/base64/PD94bWwgPz48c2xpZGVzaG93CnRpdGxlPSJTYW1wbGUgU2xpZGUgU2hvdyIKZGF0ZT0iRGF0ZSBvZiBwdWJsaWNhdGlvbiIKYXV0aG9yPSJZb3VycyBUcnVseSI+PHNsaWRlIHR5cGU9ImFsbCI+PHRpdGxlPldha2UgdXAgdG8gV29uZGVyV2lkZ2V0cyE8L3RpdGxlPjwvc2xpZGU+PHNsaWRlIHR5cGU9ImFsbCI+PHRpdGxlPk92ZXJ2aWV3PC90aXRsZT48aXRlbT5XaHkgPGVtPldvbmRlcldpZGdldHM8L2VtPiBhcmUgZ3JlYXQ8L2l0ZW0+PGl0ZW0vPjxpdGVtPldobyA8ZW0+YnV5czwvZW0+IFdvbmRlcldpZGdldHM8L2l0ZW0+PC9zbGlkZT48L3NsaWRlc2hvdz4=") - if err != nil { - t.Fatal(err) - } - assert.Equal(t, "Sample Slide Show", ssp.Title) - assert.Equal(t, 2, len(ssp.Slides)) - assert.Equal(t, "Overview", ssp.Slides[1].Title) + var ss slideshow + err = client.Get(&ss, "/get/xml") + require.NoError(t, err) + assert.Equal(t, "Sample Slide Show", ss.Title) + assert.Equal(t, 2, len(ss.Slides)) + assert.Equal(t, "Overview", ss.Slides[1].Title) // yaml - s = nil - err = client.Get(&s, "/base64/c2xpZGVzaG93OgogIGF1dGhvcjogWW91cnMgVHJ1bHkKICBkYXRlOiBkYXRlIG9mIHB1YmxpY2F0aW9uCiAgc2xpZGVzOgogIC0gdGl0bGU6IFdha2UgdXAgdG8gV29uZGVyV2lkZ2V0cyEKICAgIHR5cGU6IGFsbAogIC0gaXRlbXM6CiAgICAtIFdoeSA8ZW0+V29uZGVyV2lkZ2V0czwvZW0+IGFyZSBncmVhdAogICAgLSBXaG8gPGVtPmJ1eXM8L2VtPiBXb25kZXJXaWRnZXRzCiAgICB0aXRsZTogT3ZlcnZpZXcKICAgIHR5cGU6IGFsbAogIHRpdGxlOiBTYW1wbGUgU2xpZGUgU2hvdw==") + s = slideShowResponse{} + err = client.Get(&s, "/get/yaml") if err != nil { t.Fatal(err) } @@ -145,72 +209,82 @@ func TestClientGet(t *testing.T) { assert.Equal(t, "Overview", s.Slideshow.Slides[1].Title) } -func TestClientPost(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org") - if err != nil { - t.Fatal(err) +func (c *ClientTestSuite) TestClientPost() { + t := c.T() + client, err := NewClient("test", "http://localhost:8080") + require.NoError(t, err) + + input := slideShowResponse{ + Slideshow: slideshow{ + Title: "Sample Slide Show", + Slides: []slide{ + { + Title: "Content", + }, + { + Title: "Overview", + }, + }, + }, } - resp := &slideShowResponse{} - err = client.Get(resp, "/json") - if err != nil { - t.Fatal(err) - } - - jsonStr := resp.String() - err = client.Post(resp, "/post", jsonStr) - if err != nil { - t.Fatal(err) - } - assert.NotNil(t, resp) + jsonStr, err := json.Marshal(input) + require.NoError(t, err) + resp := slideShowResponse{} + err = client.Post(&resp, "/req2resp", jsonStr) + require.NoError(t, err) + assert.Equal(t, input.Slideshow, resp.Slideshow) assert.Equal(t, http.MethodPost, resp.Resp.Request.Method) } -func TestClientPut(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org") - if err != nil { - t.Fatal(err) +func (c *ClientTestSuite) TestClientPut() { + t := c.T() + client, err := NewClient("test", "http://localhost:8080") + require.NoError(t, err) + + input := slideShowResponse{ + Slideshow: slideshow{ + Title: "Sample Slide Show", + Slides: []slide{ + { + Title: "Content", + }, + { + Title: "Overview", + }, + }, + }, } - resp := &slideShowResponse{} - err = client.Get(resp, "/json") - if err != nil { - t.Fatal(err) - } - - jsonStr := resp.String() - err = client.Put(resp, "/put", jsonStr) - if err != nil { - t.Fatal(err) - } - assert.NotNil(t, resp) + jsonStr, err := json.Marshal(input) + require.NoError(t, err) + resp := slideShowResponse{} + err = client.Put(&resp, "/req2resp", jsonStr) + require.NoError(t, err) + assert.Equal(t, input.Slideshow, resp.Slideshow) assert.Equal(t, http.MethodPut, resp.Resp.Request.Method) } -func TestClientDelete(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org") - if err != nil { - t.Fatal(err) - } +func (c *ClientTestSuite) TestClientDelete() { + t := c.T() + client, err := NewClient("test", "http://localhost:8080") + require.NoError(t, err) resp := &slideShowResponse{} - err = client.Delete(resp, "/delete") - if err != nil { - t.Fatal(err) - } + err = client.Delete(resp, "/req2resp") + require.NoError(t, err) defer resp.Resp.Body.Close() + assert.NotNil(t, resp) assert.Equal(t, http.MethodDelete, resp.Resp.Request.Method) } -func TestClientHead(t *testing.T) { - client, err := NewClient("test", "http://beego.gocn.vip") - if err != nil { - t.Fatal(err) - } - +func (c *ClientTestSuite) TestClientHead() { + t := c.T() + client, err := NewClient("test", "http://localhost:8080") + require.NoError(t, err) resp := &slideShowResponse{} - err = client.Head(resp, "") + err = client.Head(resp, "/req2resp") if err != nil { t.Fatal(err) } diff --git a/client/httplib/httplib.go b/client/httplib/httplib.go index 304c5909..30a814c0 100644 --- a/client/httplib/httplib.go +++ b/client/httplib/httplib.go @@ -27,7 +27,6 @@ // t.Fatal(err) // } // fmt.Println(str) -// package httplib import ( @@ -38,7 +37,6 @@ import ( "encoding/json" "encoding/xml" "io" - "io/ioutil" "mime/multipart" "net" "net/http" @@ -225,9 +223,9 @@ func (b *BeegoHTTPRequest) SetTransport(transport http.RoundTripper) *BeegoHTTPR // example: // // func(req *http.Request) (*url.URL, error) { -// u, _ := url.ParseRequestURI("http://127.0.0.1:8118") -// return u, nil -// } +// u, _ := url.ParseRequestURI("http://127.0.0.1:8118") +// return u, nil +// } func (b *BeegoHTTPRequest) SetProxy(proxy func(*http.Request) (*url.URL, error)) *BeegoHTTPRequest { b.setting.Proxy = proxy return b @@ -284,16 +282,16 @@ func (b *BeegoHTTPRequest) Body(data interface{}) *BeegoHTTPRequest { switch t := data.(type) { case string: bf := bytes.NewBufferString(t) - b.req.Body = ioutil.NopCloser(bf) + b.req.Body = io.NopCloser(bf) b.req.GetBody = func() (io.ReadCloser, error) { - return ioutil.NopCloser(bf), nil + return io.NopCloser(bf), nil } b.req.ContentLength = int64(len(t)) case []byte: bf := bytes.NewBuffer(t) - b.req.Body = ioutil.NopCloser(bf) + b.req.Body = io.NopCloser(bf) b.req.GetBody = func() (io.ReadCloser, error) { - return ioutil.NopCloser(bf), nil + return io.NopCloser(bf), nil } b.req.ContentLength = int64(len(t)) default: @@ -309,9 +307,9 @@ func (b *BeegoHTTPRequest) XMLBody(obj interface{}) (*BeegoHTTPRequest, error) { if err != nil { return b, berror.Wrap(err, InvalidXMLBody, "obj could not be converted to XML data") } - b.req.Body = ioutil.NopCloser(bytes.NewReader(byts)) + b.req.Body = io.NopCloser(bytes.NewReader(byts)) b.req.GetBody = func() (io.ReadCloser, error) { - return ioutil.NopCloser(bytes.NewReader(byts)), nil + return io.NopCloser(bytes.NewReader(byts)), nil } b.req.ContentLength = int64(len(byts)) b.req.Header.Set(contentTypeKey, "application/xml") @@ -326,7 +324,7 @@ func (b *BeegoHTTPRequest) YAMLBody(obj interface{}) (*BeegoHTTPRequest, error) if err != nil { return b, berror.Wrap(err, InvalidYAMLBody, "obj could not be converted to YAML data") } - b.req.Body = ioutil.NopCloser(bytes.NewReader(byts)) + b.req.Body = io.NopCloser(bytes.NewReader(byts)) b.req.ContentLength = int64(len(byts)) b.req.Header.Set(contentTypeKey, "application/x+yaml") } @@ -340,7 +338,7 @@ func (b *BeegoHTTPRequest) JSONBody(obj interface{}) (*BeegoHTTPRequest, error) if err != nil { return b, berror.Wrap(err, InvalidJSONBody, "obj could not be converted to JSON body") } - b.req.Body = ioutil.NopCloser(bytes.NewReader(byts)) + b.req.Body = io.NopCloser(bytes.NewReader(byts)) b.req.ContentLength = int64(len(byts)) b.req.Header.Set(contentTypeKey, "application/json") } @@ -401,7 +399,7 @@ func (b *BeegoHTTPRequest) handleFiles() { _ = pw.Close() }() b.Header(contentTypeKey, bodyWriter.FormDataContentType()) - b.req.Body = ioutil.NopCloser(pr) + b.req.Body = io.NopCloser(pr) b.Header("Transfer-Encoding", "chunked") } @@ -592,10 +590,10 @@ func (b *BeegoHTTPRequest) Bytes() ([]byte, error) { if err != nil { return nil, berror.Wrap(err, ReadGzipBodyFailed, "building gzip reader failed") } - b.body, err = ioutil.ReadAll(reader) + b.body, err = io.ReadAll(reader) return b.body, berror.Wrap(err, ReadGzipBodyFailed, "reading gzip data failed") } - b.body, err = ioutil.ReadAll(resp.Body) + b.body, err = io.ReadAll(resp.Body) return b.body, err } diff --git a/client/httplib/httplib_test.go b/client/httplib/httplib_test.go index 39828d08..6c823223 100644 --- a/client/httplib/httplib_test.go +++ b/client/httplib/httplib_test.go @@ -17,9 +17,10 @@ package httplib import ( "bytes" "context" + json "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net" "net/http" "os" @@ -27,19 +28,104 @@ import ( "testing" "time" + "github.com/stretchr/testify/suite" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestResponse(t *testing.T) { - req := Get("http://httpbin.org/get") - resp, err := req.Response() - require.NoError(t, err) - t.Log(resp) +type HttplibTestSuite struct { + suite.Suite + l net.Listener } -func TestDoRequest(t *testing.T) { - req := Get("https://goolnk.com/33BD2j") +func (h *HttplibTestSuite) SetupSuite() { + listener, err := net.Listen("tcp", ":8080") + require.NoError(h.T(), err) + h.l = listener + + handler := http.NewServeMux() + + handler.HandleFunc("/get", func(writer http.ResponseWriter, request *http.Request) { + agent := request.Header.Get("User-Agent") + _, _ = writer.Write([]byte("hello, " + agent)) + }) + + handler.HandleFunc("/put", func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte("hello, put")) + }) + + handler.HandleFunc("/post", func(writer http.ResponseWriter, request *http.Request) { + body, _ := io.ReadAll(request.Body) + _, _ = writer.Write(body) + }) + + handler.HandleFunc("/delete", func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte("hello, delete")) + }) + + handler.HandleFunc("/cookies/set", func(writer http.ResponseWriter, request *http.Request) { + k1 := request.URL.Query().Get("k1") + http.SetCookie(writer, &http.Cookie{ + Name: "k1", + Value: k1, + }) + _, _ = writer.Write([]byte("hello, set cookie")) + }) + + handler.HandleFunc("/cookies", func(writer http.ResponseWriter, request *http.Request) { + body := request.Cookies()[0].String() + _, _ = writer.Write([]byte(body)) + }) + + handler.HandleFunc("/basic-auth/user/passwd", func(writer http.ResponseWriter, request *http.Request) { + _, _, ok := request.BasicAuth() + if ok { + _, _ = writer.Write([]byte("authenticated")) + } else { + _, _ = writer.Write([]byte("no auth")) + } + }) + + handler.HandleFunc("/headers", func(writer http.ResponseWriter, request *http.Request) { + agent := request.Header.Get("User-Agent") + _, _ = writer.Write([]byte(agent)) + }) + + handler.HandleFunc("/ip", func(writer http.ResponseWriter, request *http.Request) { + data := map[string]string{"origin": "127.0.0.1"} + jsonBytes, _ := json.Marshal(data) + _, _ = writer.Write(jsonBytes) + }) + + handler.HandleFunc("/redirect", func(writer http.ResponseWriter, request *http.Request) { + http.Redirect(writer, request, "redirect_dst", http.StatusTemporaryRedirect) + }) + handler.HandleFunc("redirect_dst", func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte("hello")) + }) + go func() { + _ = http.Serve(listener, handler) + }() +} + +func (h *HttplibTestSuite) TearDownSuite() { + _ = h.l.Close() +} + +func TestHttplib(t *testing.T) { + suite.Run(t, &HttplibTestSuite{}) +} + +func (h *HttplibTestSuite) TestResponse() { + req := Get("http://localhost:8080/get") + _, err := req.Response() + require.NoError(h.T(), err) +} + +func (h *HttplibTestSuite) TestDoRequest() { + t := h.T() + req := Get("http://localhost:8080/redirect") retryAmount := 1 req.Retries(1) req.RetryDelay(1400 * time.Millisecond) @@ -63,107 +149,79 @@ func TestDoRequest(t *testing.T) { } } -func TestGet(t *testing.T) { - req := Get("http://httpbin.org/get") +func (h *HttplibTestSuite) TestGet() { + t := h.T() + req := Get("http://localhost:8080/get") b, err := req.Bytes() require.NoError(t, err) - t.Log(b) s, err := req.String() require.NoError(t, err) - t.Log(s) require.Equal(t, string(b), s) } -func TestSimplePost(t *testing.T) { +func (h *HttplibTestSuite) TestSimplePost() { + t := h.T() v := "smallfish" - req := Post("http://httpbin.org/post") + req := Post("http://localhost:8080/post") req.Param("username", v) str, err := req.String() require.NoError(t, err) - t.Log(str) + n := strings.Index(str, v) + require.NotEqual(t, -1, n) +} + +func (h *HttplibTestSuite) TestSimplePut() { + t := h.T() + _, err := Put("http://localhost:8080/put").String() + require.NoError(t, err) +} + +func (h *HttplibTestSuite) TestSimpleDelete() { + t := h.T() + _, err := Delete("http://localhost:8080/delete").String() + require.NoError(t, err) +} + +func (h *HttplibTestSuite) TestSimpleDeleteParam() { + t := h.T() + _, err := Delete("http://localhost:8080/delete").Param("key", "val").String() + require.NoError(t, err) +} + +func (h *HttplibTestSuite) TestWithCookie() { + t := h.T() + v := "smallfish" + _, err := Get("http://localhost:8080/cookies/set?k1=" + v).SetEnableCookie(true).String() + require.NoError(t, err) + + str, err := Get("http://localhost:8080/cookies").SetEnableCookie(true).String() + require.NoError(t, err) n := strings.Index(str, v) require.NotEqual(t, -1, n) } -// func TestPostFile(t *testing.T) { -// v := "smallfish" -// req := Post("http://httpbin.org/post") -// req.Debug(true) -// req.Param("username", v) -// req.PostFile("uploadfile", "httplib_test.go") - -// str, err := req.String() -// if err != nil { -// t.Fatal(err) -// } -// t.Log(str) - -// n := strings.Index(str, v) -// if n == -1 { -// t.Fatal(v + " not found in post") -// } -// } - -func TestSimplePut(t *testing.T) { - str, err := Put("http://httpbin.org/put").String() +func (h *HttplibTestSuite) TestWithBasicAuth() { + t := h.T() + str, err := Get("http://localhost:8080/basic-auth/user/passwd").SetBasicAuth("user", "passwd").String() require.NoError(t, err) - t.Log(str) -} - -func TestSimpleDelete(t *testing.T) { - str, err := Delete("http://httpbin.org/delete").String() - require.NoError(t, err) - t.Log(str) -} - -func TestSimpleDeleteParam(t *testing.T) { - str, err := Delete("http://httpbin.org/delete").Param("key", "val").String() - require.NoError(t, err) - t.Log(str) -} - -func TestWithCookie(t *testing.T) { - v := "smallfish" - str, err := Get("http://httpbin.org/cookies/set?k1=" + v).SetEnableCookie(true).String() - require.NoError(t, err) - t.Log(str) - - str, err = Get("http://httpbin.org/cookies").SetEnableCookie(true).String() - require.NoError(t, err) - t.Log(str) - - n := strings.Index(str, v) - if n == -1 { - t.Fatal(v + " not found in cookie") - } -} - -func TestWithBasicAuth(t *testing.T) { - str, err := Get("http://httpbin.org/basic-auth/user/passwd").SetBasicAuth("user", "passwd").String() - require.NoError(t, err) - t.Log(str) n := strings.Index(str, "authenticated") - if n == -1 { - t.Fatal("authenticated not found in response") - } + require.NotEqual(t, -1, n) } -func TestWithUserAgent(t *testing.T) { +func (h *HttplibTestSuite) TestWithUserAgent() { + t := h.T() v := "beego" - str, err := Get("http://httpbin.org/headers").SetUserAgent(v).String() + str, err := Get("http://localhost:8080/headers").SetUserAgent(v).String() require.NoError(t, err) - t.Log(str) - n := strings.Index(str, v) - if n == -1 { - t.Fatal(v + " not found in user-agent") - } + require.NotEqual(t, -1, n) } -func TestWithSetting(t *testing.T) { +func (h *HttplibTestSuite) TestWithSetting() { + t := h.T() v := "beego" var setting BeegoHTTPSettings setting.EnableCookie = true @@ -181,75 +239,68 @@ func TestWithSetting(t *testing.T) { setting.ReadWriteTimeout = 5 * time.Second SetDefaultSetting(setting) - str, err := Get("http://httpbin.org/get").String() + str, err := Get("http://localhost:8080/get").String() require.NoError(t, err) - t.Log(str) - n := strings.Index(str, v) - if n == -1 { - t.Fatal(v + " not found in user-agent") - } + require.NotEqual(t, -1, n) } -func TestToJson(t *testing.T) { - req := Get("http://httpbin.org/ip") +func (h *HttplibTestSuite) TestToJson() { + t := h.T() + req := Get("http://localhost:8080/ip") resp, err := req.Response() require.NoError(t, err) t.Log(resp) - // httpbin will return http remote addr type IP struct { Origin string `json:"origin"` } var ip IP err = req.ToJSON(&ip) require.NoError(t, err) - t.Log(ip.Origin) + require.Equal(t, "127.0.0.1", ip.Origin) + ips := strings.Split(ip.Origin, ",") - if len(ips) == 0 { - t.Fatal("response is not valid ip") - } - for i := range ips { - if net.ParseIP(strings.TrimSpace(ips[i])).To4() == nil { - t.Fatal("response is not valid ip") - } - } + require.NotEmpty(t, ips) } -func TestToFile(t *testing.T) { +func (h *HttplibTestSuite) TestToFile() { + t := h.T() f := "beego_testfile" - req := Get("http://httpbin.org/ip") + req := Get("http://localhost:8080/ip") err := req.ToFile(f) require.NoError(t, err) defer os.Remove(f) - b, err := ioutil.ReadFile(f) - if n := bytes.Index(b, []byte("origin")); n == -1 { - t.Fatal(err) - } + + b, err := os.ReadFile(f) + n := bytes.Index(b, []byte("origin")) + require.NotEqual(t, -1, n) } -func TestToFileDir(t *testing.T) { +func (h *HttplibTestSuite) TestToFileDir() { + t := h.T() f := "./files/beego_testfile" - req := Get("http://httpbin.org/ip") + req := Get("http://localhost:8080/ip") err := req.ToFile(f) require.NoError(t, err) defer os.RemoveAll("./files") - b, err := ioutil.ReadFile(f) - if n := bytes.Index(b, []byte("origin")); n == -1 { - t.Fatal(err) - } + b, err := os.ReadFile(f) + require.NoError(t, err) + n := bytes.Index(b, []byte("origin")) + require.NotEqual(t, -1, n) } -func TestHeader(t *testing.T) { - req := Get("http://httpbin.org/headers") +func (h *HttplibTestSuite) TestHeader() { + t := h.T() + req := Get("http://localhost:8080/headers") req.Header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36") - str, err := req.String() + _, err := req.String() require.NoError(t, err) - t.Log(str) } // TestAddFilter make sure that AddFilters only work for the specific request -func TestAddFilter(t *testing.T) { +func (h *HttplibTestSuite) TestAddFilter() { + t := h.T() req := Get("http://beego.vip") req.AddFilters(func(next Filter) Filter { return func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) { @@ -261,7 +312,8 @@ func TestAddFilter(t *testing.T) { assert.Equal(t, 1, len(req.setting.FilterChains)-len(r.setting.FilterChains)) } -func TestFilterChainOrder(t *testing.T) { +func (h *HttplibTestSuite) TestFilterChainOrder() { + t := h.T() req := Get("http://beego.vip") req.AddFilters(func(next Filter) Filter { return func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) { @@ -282,24 +334,34 @@ func TestFilterChainOrder(t *testing.T) { assert.Equal(t, "first", string(data)) } -func TestHead(t *testing.T) { +func (h *HttplibTestSuite) TestHead() { + t := h.T() req := Head("http://beego.vip") assert.NotNil(t, req) assert.Equal(t, "HEAD", req.req.Method) } -func TestDelete(t *testing.T) { +func (h *HttplibTestSuite) TestDelete() { + t := h.T() req := Delete("http://beego.vip") assert.NotNil(t, req) assert.Equal(t, "DELETE", req.req.Method) } -func TestPost(t *testing.T) { +func (h *HttplibTestSuite) TestPost() { + t := h.T() req := Post("http://beego.vip") assert.NotNil(t, req) assert.Equal(t, "POST", req.req.Method) } +func (h *HttplibTestSuite) TestPut() { + t := h.T() + req := Put("http://beego.vip") + assert.NotNil(t, req) + assert.Equal(t, "PUT", req.req.Method) +} + func TestNewBeegoRequest(t *testing.T) { req := NewBeegoRequest("http://beego.vip", "GET") assert.NotNil(t, req) @@ -341,12 +403,6 @@ func TestBeegoHTTPRequestSetProtocolVersion(t *testing.T) { assert.Equal(t, 1, req.req.ProtoMinor) } -func TestPut(t *testing.T) { - req := Put("http://beego.vip") - assert.NotNil(t, req) - assert.Equal(t, "PUT", req.req.Method) -} - func TestBeegoHTTPRequestHeader(t *testing.T) { req := Post("http://beego.vip") key, value := "test-header", "test-header-value" diff --git a/client/orm/cmd.go b/client/orm/cmd.go index 9819badb..cd6fd5cc 100644 --- a/client/orm/cmd.go +++ b/client/orm/cmd.go @@ -20,6 +20,10 @@ import ( "fmt" "os" "strings" + + "github.com/beego/beego/v2/client/orm/internal/utils" + + "github.com/beego/beego/v2/client/orm/internal/models" ) type commander interface { @@ -53,7 +57,7 @@ func RunCommand() { BootStrap() - args := argString(os.Args[2:]) + args := utils.ArgString(os.Args[2:]) name := args.Get(0) if name == "help" { @@ -112,7 +116,7 @@ func (d *commandSyncDb) Run() error { for i, mi := range defaultModelCache.allOrdered() { query := drops[i] if !d.noInfo { - fmt.Printf("drop table `%s`\n", mi.table) + fmt.Printf("drop table `%s`\n", mi.Table) } _, err := db.Exec(query) if d.verbose { @@ -143,18 +147,18 @@ func (d *commandSyncDb) Run() error { ctx := context.Background() for i, mi := range defaultModelCache.allOrdered() { - if !isApplicableTableForDB(mi.addrField, d.al.Name) { - fmt.Printf("table `%s` is not applicable to database '%s'\n", mi.table, d.al.Name) + if !models.IsApplicableTableForDB(mi.AddrField, d.al.Name) { + fmt.Printf("table `%s` is not applicable to database '%s'\n", mi.Table, d.al.Name) continue } - if tables[mi.table] { + if tables[mi.Table] { if !d.noInfo { - fmt.Printf("table `%s` already exists, skip\n", mi.table) + fmt.Printf("table `%s` already exists, skip\n", mi.Table) } - var fields []*fieldInfo - columns, err := d.al.DbBaser.GetColumns(ctx, db, mi.table) + var fields []*models.FieldInfo + columns, err := d.al.DbBaser.GetColumns(ctx, db, mi.Table) if err != nil { if d.rtOnError { return err @@ -162,8 +166,8 @@ func (d *commandSyncDb) Run() error { fmt.Printf(" %s\n", err.Error()) } - for _, fi := range mi.fields.fieldsDB { - if _, ok := columns[fi.column]; !ok { + for _, fi := range mi.Fields.FieldsDB { + if _, ok := columns[fi.Column]; !ok { fields = append(fields, fi) } } @@ -172,7 +176,7 @@ func (d *commandSyncDb) Run() error { query := getColumnAddQuery(d.al, fi) if !d.noInfo { - fmt.Printf("add column `%s` for table `%s`\n", fi.fullName, mi.table) + fmt.Printf("add column `%s` for table `%s`\n", fi.FullName, mi.Table) } _, err := db.Exec(query) @@ -187,7 +191,7 @@ func (d *commandSyncDb) Run() error { } } - for _, idx := range indexes[mi.table] { + for _, idx := range indexes[mi.Table] { if !d.al.DbBaser.IndexExists(ctx, db, idx.Table, idx.Name) { if !d.noInfo { fmt.Printf("create index `%s` for table `%s`\n", idx.Name, idx.Table) @@ -211,11 +215,11 @@ func (d *commandSyncDb) Run() error { } if !d.noInfo { - fmt.Printf("create table `%s` \n", mi.table) + fmt.Printf("create table `%s` \n", mi.Table) } queries := []string{createQueries[i]} - for _, idx := range indexes[mi.table] { + for _, idx := range indexes[mi.Table] { queries = append(queries, idx.SQL) } @@ -265,7 +269,7 @@ func (d *commandSQLAll) Run() error { var all []string for i, mi := range defaultModelCache.allOrdered() { queries := []string{createQueries[i]} - for _, idx := range indexes[mi.table] { + for _, idx := range indexes[mi.Table] { queries = append(queries, idx.SQL) } sql := strings.Join(queries, "\n") diff --git a/client/orm/cmd_utils.go b/client/orm/cmd_utils.go index 7b795b22..b327dd6f 100644 --- a/client/orm/cmd_utils.go +++ b/client/orm/cmd_utils.go @@ -17,6 +17,8 @@ package orm import ( "fmt" "strings" + + "github.com/beego/beego/v2/client/orm/internal/models" ) type dbIndex struct { @@ -26,17 +28,22 @@ type dbIndex struct { } // get database column type string. -func getColumnTyp(al *alias, fi *fieldInfo) (col string) { +func getColumnTyp(al *alias, fi *models.FieldInfo) (col string) { T := al.DbBaser.DbTypes() - fieldType := fi.fieldType - fieldSize := fi.size + fieldType := fi.FieldType + fieldSize := fi.Size + + defer func() { + // handling the placeholder, including %COL% + col = strings.ReplaceAll(col, "%COL%", fi.Column) + }() checkColumn: switch fieldType { case TypeBooleanField: col = T["bool"] case TypeVarCharField: - if al.Driver == DRPostgres && fi.toText { + if al.Driver == DRPostgres && fi.ToText { col = T["string-text"] } else { col = fmt.Sprintf(T["string"], fieldSize) @@ -51,11 +58,11 @@ checkColumn: col = T["time.Time-date"] case TypeDateTimeField: // the precision of sqlite is not implemented - if al.Driver == 2 || fi.timePrecision == nil { + if al.Driver == 2 || fi.TimePrecision == nil { col = T["time.Time"] } else { s := T["time.Time-precision"] - col = fmt.Sprintf(s, *fi.timePrecision) + col = fmt.Sprintf(s, *fi.TimePrecision) } case TypeBitField: @@ -85,7 +92,7 @@ checkColumn: if !strings.Contains(s, "%d") { col = s } else { - col = fmt.Sprintf(s, fi.digits, fi.decimals) + col = fmt.Sprintf(s, fi.Digits, fi.Decimals) } case TypeJSONField: if al.Driver != DRPostgres { @@ -100,8 +107,8 @@ checkColumn: } col = T["jsonb"] case RelForeignKey, RelOneToOne: - fieldType = fi.relModelInfo.fields.pk.fieldType - fieldSize = fi.relModelInfo.fields.pk.size + fieldType = fi.RelModelInfo.Fields.Pk.FieldType + fieldSize = fi.RelModelInfo.Fields.Pk.Size goto checkColumn } @@ -109,34 +116,34 @@ checkColumn: } // create alter sql string. -func getColumnAddQuery(al *alias, fi *fieldInfo) string { +func getColumnAddQuery(al *alias, fi *models.FieldInfo) string { Q := al.DbBaser.TableQuote() typ := getColumnTyp(al, fi) - if !fi.null { + if !fi.Null { typ += " " + "NOT NULL" } return fmt.Sprintf("ALTER TABLE %s%s%s ADD COLUMN %s%s%s %s %s", - Q, fi.mi.table, Q, - Q, fi.column, Q, + Q, fi.Mi.Table, Q, + Q, fi.Column, Q, typ, getColumnDefault(fi), ) } // Get string value for the attribute "DEFAULT" for the CREATE, ALTER commands -func getColumnDefault(fi *fieldInfo) string { +func getColumnDefault(fi *models.FieldInfo) string { var v, t, d string // Skip default attribute if field is in relations - if fi.rel || fi.reverse { + if fi.Rel || fi.Reverse { return v } t = " DEFAULT '%s' " // These defaults will be useful if there no config value orm:"default" and NOT NULL is on - switch fi.fieldType { + switch fi.FieldType { case TypeTimeField, TypeDateField, TypeDateTimeField, TypeTextField: return v @@ -153,14 +160,14 @@ func getColumnDefault(fi *fieldInfo) string { d = "{}" } - if fi.colDefault { - if !fi.initial.Exist() { + if fi.ColDefault { + if !fi.Initial.Exist() { v = fmt.Sprintf(t, "") } else { - v = fmt.Sprintf(t, fi.initial.String()) + v = fmt.Sprintf(t, fi.Initial.String()) } } else { - if !fi.null { + if !fi.Null { v = fmt.Sprintf(t, d) } } diff --git a/client/orm/cmd_utils_test.go b/client/orm/cmd_utils_test.go new file mode 100644 index 00000000..1ba42990 --- /dev/null +++ b/client/orm/cmd_utils_test.go @@ -0,0 +1,39 @@ +package orm + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/beego/beego/v2/client/orm/internal/models" +) + +func Test_getColumnTyp(t *testing.T) { + testCases := []struct { + name string + fi *models.FieldInfo + al *alias + + wantCol string + }{ + { + // https://github.com/beego/beego/issues/5254 + name: "issue 5254", + fi: &models.FieldInfo{ + FieldType: TypePositiveIntegerField, + Column: "my_col", + }, + al: &alias{ + DbBaser: newdbBasePostgres(), + }, + wantCol: `bigint CHECK("my_col" >= 0)`, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + col := getColumnTyp(tc.al, tc.fi) + assert.Equal(t, tc.wantCol, col) + }) + } +} diff --git a/client/orm/db.go b/client/orm/db.go index cbaa81ad..8bb4bec4 100644 --- a/client/orm/db.go +++ b/client/orm/db.go @@ -23,13 +23,15 @@ import ( "strings" "time" - "github.com/beego/beego/v2/client/orm/hints" -) + "github.com/beego/beego/v2/client/orm/internal/buffers" -const ( - formatTime = "15:04:05" - formatDate = "2006-01-02" - formatDateTime = "2006-01-02 15:04:05" + "github.com/beego/beego/v2/client/orm/internal/logs" + + "github.com/beego/beego/v2/client/orm/internal/utils" + + "github.com/beego/beego/v2/client/orm/internal/models" + + "github.com/beego/beego/v2/client/orm/hints" ) // ErrMissPK missing pk error @@ -72,8 +74,8 @@ type dbBase struct { // check dbBase implements dbBaser interface. var _ dbBaser = new(dbBase) -// get struct columns values as interface slice. -func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string, skipAuto bool, insert bool, names *[]string, tz *time.Location) (values []interface{}, autoFields []string, err error) { +// get struct Columns values as interface slice. +func (d *dbBase) collectValues(mi *models.ModelInfo, ind reflect.Value, cols []string, skipAuto bool, insert bool, names *[]string, tz *time.Location) (values []interface{}, autoFields []string, err error) { if names == nil { ns := make([]string, 0, len(cols)) names = &ns @@ -81,13 +83,13 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string, values = make([]interface{}, 0, len(cols)) for _, column := range cols { - var fi *fieldInfo - if fi, _ = mi.fields.GetByAny(column); fi != nil { - column = fi.column + var fi *models.FieldInfo + if fi, _ = mi.Fields.GetByAny(column); fi != nil { + column = fi.Column } else { - panic(fmt.Errorf("wrong db field/column name `%s` for model `%s`", column, mi.fullName)) + panic(fmt.Errorf("wrong db field/column name `%s` for model `%s`", column, mi.FullName)) } - if !fi.dbcol || fi.auto && skipAuto { + if !fi.DBcol || fi.Auto && skipAuto { continue } value, err := d.collectFieldValue(mi, fi, ind, insert, tz) @@ -96,8 +98,8 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string, } // ignore empty value auto field - if insert && fi.auto { - if fi.fieldType&IsPositiveIntegerField > 0 { + if insert && fi.Auto { + if fi.FieldType&IsPositiveIntegerField > 0 { if vu, ok := value.(uint64); !ok || vu == 0 { continue } @@ -106,7 +108,7 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string, continue } } - autoFields = append(autoFields, fi.column) + autoFields = append(autoFields, fi.Column) } *names, values = append(*names, column), append(values, value) @@ -116,17 +118,17 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string, } // get one field value in struct column as interface. -func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Value, insert bool, tz *time.Location) (interface{}, error) { +func (d *dbBase) collectFieldValue(mi *models.ModelInfo, fi *models.FieldInfo, ind reflect.Value, insert bool, tz *time.Location) (interface{}, error) { var value interface{} - if fi.pk { + if fi.Pk { _, value, _ = getExistPk(mi, ind) } else { - field := ind.FieldByIndex(fi.fieldIndex) - if fi.isFielder { - f := field.Addr().Interface().(Fielder) + field := ind.FieldByIndex(fi.FieldIndex) + if fi.IsFielder { + f := field.Addr().Interface().(models.Fielder) value = f.RawValue() } else { - switch fi.fieldType { + switch fi.FieldType { case TypeBooleanField: if nb, ok := field.Interface().(sql.NullBool); ok { value = nil @@ -172,7 +174,7 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val } else { vu := field.Interface() if _, ok := vu.(float32); ok { - value, _ = StrTo(ToStr(vu)).Float64() + value, _ = utils.StrTo(utils.ToStr(vu)).Float64() } else { value = field.Float() } @@ -189,7 +191,7 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val } default: switch { - case fi.fieldType&IsPositiveIntegerField > 0: + case fi.FieldType&IsPositiveIntegerField > 0: if field.Kind() == reflect.Ptr { if field.IsNil() { value = nil @@ -199,7 +201,7 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val } else { value = field.Uint() } - case fi.fieldType&IsIntegerField > 0: + case fi.FieldType&IsIntegerField > 0: if ni, ok := field.Interface().(sql.NullInt64); ok { value = nil if ni.Valid { @@ -214,25 +216,25 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val } else { value = field.Int() } - case fi.fieldType&IsRelField > 0: + case fi.FieldType&IsRelField > 0: if field.IsNil() { value = nil } else { - if _, vu, ok := getExistPk(fi.relModelInfo, reflect.Indirect(field)); ok { + if _, vu, ok := getExistPk(fi.RelModelInfo, reflect.Indirect(field)); ok { value = vu } else { value = nil } } - if !fi.null && value == nil { - return nil, fmt.Errorf("field `%s` cannot be NULL", fi.fullName) + if !fi.Null && value == nil { + return nil, fmt.Errorf("field `%s` cannot be NULL", fi.FullName) } } } } - switch fi.fieldType { + switch fi.FieldType { case TypeTimeField, TypeDateField, TypeDateTimeField: - if fi.autoNow || fi.autoNowAdd && insert { + if fi.AutoNow || fi.AutoNowAdd && insert { if insert { if t, ok := value.(time.Time); ok && !t.IsZero() { break @@ -241,8 +243,8 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val tnow := time.Now() d.ins.TimeToDB(&tnow, tz) value = tnow - if fi.isFielder { - f := field.Addr().Interface().(Fielder) + if fi.IsFielder { + f := field.Addr().Interface().(models.Fielder) f.SetRaw(tnow.In(DefaultTimeLoc)) } else if field.Kind() == reflect.Ptr { v := tnow.In(DefaultTimeLoc) @@ -253,8 +255,8 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val } case TypeJSONField, TypeJsonbField: if s, ok := value.(string); (ok && len(s) == 0) || value == nil { - if fi.colDefault && fi.initial.Exist() { - value = fi.initial.String() + if fi.ColDefault && fi.Initial.Exist() { + value = fi.Initial.String() } else { value = nil } @@ -265,14 +267,14 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val } // PrepareInsert create insert sql preparation statement object. -func (d *dbBase) PrepareInsert(ctx context.Context, q dbQuerier, mi *modelInfo) (stmtQuerier, string, error) { +func (d *dbBase) PrepareInsert(ctx context.Context, q dbQuerier, mi *models.ModelInfo) (stmtQuerier, string, error) { Q := d.ins.TableQuote() - dbcols := make([]string, 0, len(mi.fields.dbcols)) - marks := make([]string, 0, len(mi.fields.dbcols)) - for _, fi := range mi.fields.fieldsDB { - if !fi.auto { - dbcols = append(dbcols, fi.column) + dbcols := make([]string, 0, len(mi.Fields.DBcols)) + marks := make([]string, 0, len(mi.Fields.DBcols)) + for _, fi := range mi.Fields.FieldsDB { + if !fi.Auto { + dbcols = append(dbcols, fi.Column) marks = append(marks, "?") } } @@ -280,7 +282,7 @@ func (d *dbBase) PrepareInsert(ctx context.Context, q dbQuerier, mi *modelInfo) sep := fmt.Sprintf("%s, %s", Q, Q) columns := strings.Join(dbcols, sep) - query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s)", Q, mi.table, Q, Q, columns, Q, qmarks) + query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s)", Q, mi.Table, Q, Q, columns, Q, qmarks) d.ins.ReplaceMarks(&query) @@ -291,8 +293,8 @@ func (d *dbBase) PrepareInsert(ctx context.Context, q dbQuerier, mi *modelInfo) } // InsertStmt insert struct with prepared statement and given struct reflect value. -func (d *dbBase) InsertStmt(ctx context.Context, stmt stmtQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { - values, _, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, nil, tz) +func (d *dbBase) InsertStmt(ctx context.Context, stmt stmtQuerier, mi *models.ModelInfo, ind reflect.Value, tz *time.Location) (int64, error) { + values, _, err := d.collectValues(mi, ind, mi.Fields.DBcols, true, true, nil, tz) if err != nil { return 0, err } @@ -311,7 +313,7 @@ func (d *dbBase) InsertStmt(ctx context.Context, stmt stmtQuerier, mi *modelInfo } // query sql ,read records and persist in dbBaser. -func (d *dbBase) Read(ctx context.Context, q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string, isForUpdate bool) error { +func (d *dbBase) Read(ctx context.Context, q dbQuerier, mi *models.ModelInfo, ind reflect.Value, tz *time.Location, cols []string, isForUpdate bool) error { var whereCols []string var args []interface{} @@ -336,8 +338,8 @@ func (d *dbBase) Read(ctx context.Context, q dbQuerier, mi *modelInfo, ind refle Q := d.ins.TableQuote() sep := fmt.Sprintf("%s, %s", Q, Q) - sels := strings.Join(mi.fields.dbcols, sep) - colsNum := len(mi.fields.dbcols) + sels := strings.Join(mi.Fields.DBcols, sep) + colsNum := len(mi.Fields.DBcols) sep = fmt.Sprintf("%s = ? AND %s", Q, Q) wheres := strings.Join(whereCols, sep) @@ -347,7 +349,7 @@ func (d *dbBase) Read(ctx context.Context, q dbQuerier, mi *modelInfo, ind refle forUpdate = "FOR UPDATE" } - query := fmt.Sprintf("SELECT %s%s%s FROM %s%s%s WHERE %s%s%s = ? %s", Q, sels, Q, Q, mi.table, Q, Q, wheres, Q, forUpdate) + query := fmt.Sprintf("SELECT %s%s%s FROM %s%s%s WHERE %s%s%s = ? %s", Q, sels, Q, Q, mi.Table, Q, Q, wheres, Q, forUpdate) refs := make([]interface{}, colsNum) for i := range refs { @@ -364,17 +366,17 @@ func (d *dbBase) Read(ctx context.Context, q dbQuerier, mi *modelInfo, ind refle } return err } - elm := reflect.New(mi.addrField.Elem().Type()) + elm := reflect.New(mi.AddrField.Elem().Type()) mind := reflect.Indirect(elm) - d.setColsValues(mi, &mind, mi.fields.dbcols, refs, tz) + d.setColsValues(mi, &mind, mi.Fields.DBcols, refs, tz) ind.Set(mind) return nil } // Insert execute insert sql dbQuerier with given struct reflect.Value. -func (d *dbBase) Insert(ctx context.Context, q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { - names := make([]string, 0, len(mi.fields.dbcols)) - values, autoFields, err := d.collectValues(mi, ind, mi.fields.dbcols, false, true, &names, tz) +func (d *dbBase) Insert(ctx context.Context, q dbQuerier, mi *models.ModelInfo, ind reflect.Value, tz *time.Location) (int64, error) { + names := make([]string, 0, len(mi.Fields.DBcols)) + values, autoFields, err := d.collectValues(mi, ind, mi.Fields.DBcols, false, true, &names, tz) if err != nil { return 0, err } @@ -391,7 +393,7 @@ func (d *dbBase) Insert(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref } // InsertMulti multi-insert sql with given slice struct reflect.Value. -func (d *dbBase) InsertMulti(ctx context.Context, q dbQuerier, mi *modelInfo, sind reflect.Value, bulk int, tz *time.Location) (int64, error) { +func (d *dbBase) InsertMulti(ctx context.Context, q dbQuerier, mi *models.ModelInfo, sind reflect.Value, bulk int, tz *time.Location) (int64, error) { var ( cnt int64 nums int @@ -399,32 +401,25 @@ func (d *dbBase) InsertMulti(ctx context.Context, q dbQuerier, mi *modelInfo, si names []string ) - // typ := reflect.Indirect(mi.addrField).Type() - length, autoFields := sind.Len(), make([]string, 0, 1) for i := 1; i <= length; i++ { ind := reflect.Indirect(sind.Index(i - 1)) - // Is this needed ? - // if !ind.Type().AssignableTo(typ) { - // return cnt, ErrArgs - // } - if i == 1 { var ( vus []interface{} err error ) - vus, autoFields, err = d.collectValues(mi, ind, mi.fields.dbcols, false, true, &names, tz) + vus, autoFields, err = d.collectValues(mi, ind, mi.Fields.DBcols, false, true, &names, tz) if err != nil { return cnt, err } values = make([]interface{}, bulk*len(vus)) nums += copy(values, vus) } else { - vus, _, err := d.collectValues(mi, ind, mi.fields.dbcols, false, true, nil, tz) + vus, _, err := d.collectValues(mi, ind, mi.Fields.DBcols, false, true, nil, tz) if err != nil { return cnt, err } @@ -456,27 +451,8 @@ func (d *dbBase) InsertMulti(ctx context.Context, q dbQuerier, mi *modelInfo, si // InsertValue execute insert sql with given struct and given values. // insert the given values, not the field values in struct. -func (d *dbBase) InsertValue(ctx context.Context, q dbQuerier, mi *modelInfo, isMulti bool, names []string, values []interface{}) (int64, error) { - Q := d.ins.TableQuote() - - marks := make([]string, len(names)) - for i := range marks { - marks[i] = "?" - } - - sep := fmt.Sprintf("%s, %s", Q, Q) - qmarks := strings.Join(marks, ", ") - columns := strings.Join(names, sep) - - multi := len(values) / len(names) - - if isMulti && multi > 1 { - qmarks = strings.Repeat(qmarks+"), (", multi-1) + qmarks - } - - query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s)", Q, mi.table, Q, Q, columns, Q, qmarks) - - d.ins.ReplaceMarks(&query) +func (d *dbBase) InsertValue(ctx context.Context, q dbQuerier, mi *models.ModelInfo, isMulti bool, names []string, values []interface{}) (int64, error) { + query := d.InsertValueSQL(names, values, isMulti, mi) if isMulti || !d.ins.HasReturningID(mi, &query) { res, err := q.ExecContext(ctx, query, values...) @@ -487,7 +463,7 @@ func (d *dbBase) InsertValue(ctx context.Context, q dbQuerier, mi *modelInfo, is lastInsertId, err := res.LastInsertId() if err != nil { - DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) + logs.DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) return lastInsertId, ErrLastInsertIdUnavailable } else { return lastInsertId, nil @@ -501,10 +477,57 @@ func (d *dbBase) InsertValue(ctx context.Context, q dbQuerier, mi *modelInfo, is return id, err } +func (d *dbBase) InsertValueSQL(names []string, values []interface{}, isMulti bool, mi *models.ModelInfo) string { + buf := buffers.Get() + defer buffers.Put(buf) + + Q := d.ins.TableQuote() + + _, _ = buf.WriteString("INSERT INTO ") + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(mi.Table) + _, _ = buf.WriteString(Q) + + _, _ = buf.WriteString(" (") + for i, name := range names { + if i > 0 { + _, _ = buf.WriteString(", ") + } + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(name) + _, _ = buf.WriteString(Q) + } + _, _ = buf.WriteString(") VALUES (") + + marks := make([]string, len(names)) + for i := range marks { + marks[i] = "?" + } + qmarks := strings.Join(marks, ", ") + + _, _ = buf.WriteString(qmarks) + + multi := len(values) / len(names) + + if isMulti && multi > 1 { + for i := 0; i < multi-1; i++ { + _, _ = buf.WriteString("), (") + _, _ = buf.WriteString(qmarks) + } + } + + _ = buf.WriteByte(')') + + query := buf.String() + d.ins.ReplaceMarks(&query) + + return query +} + // InsertOrUpdate a row // If your primary key or unique column conflict will update // If no will insert -func (d *dbBase) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *modelInfo, ind reflect.Value, a *alias, args ...string) (int64, error) { +func (d *dbBase) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *models.ModelInfo, ind reflect.Value, a *alias, args ...string) (int64, error) { args0 := "" iouStr := "" argsMap := map[string]string{} @@ -529,10 +552,9 @@ func (d *dbBase) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *modelInfo, } } - isMulti := false - names := make([]string, 0, len(mi.fields.dbcols)-1) + names := make([]string, 0, len(mi.Fields.DBcols)-1) Q := d.ins.TableQuote() - values, _, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, &names, a.TZ) + values, _, err := d.collectValues(mi, ind, mi.Fields.DBcols, true, true, &names, a.TZ) if err != nil { return 0, err } @@ -556,7 +578,7 @@ func (d *dbBase) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *modelInfo, case DRPostgres: if conflitValue != nil { // postgres ON CONFLICT DO UPDATE SET can`t use colu=colu+values - updates[i] = fmt.Sprintf("%s=(select %s from %s where %s = ? )", v, valueStr, mi.table, args0) + updates[i] = fmt.Sprintf("%s=(select %s from %s where %s = ? )", v, valueStr, mi.Table, args0) updateValues = append(updateValues, conflitValue) } else { return 0, fmt.Errorf("`%s` must be in front of `%s` in your struct", args0, v) @@ -575,26 +597,17 @@ func (d *dbBase) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *modelInfo, qupdates := strings.Join(updates, ", ") columns := strings.Join(names, sep) - multi := len(values) / len(names) - - if isMulti { - qmarks = strings.Repeat(qmarks+"), (", multi-1) + qmarks - } // conflitValue maybe is a int,can`t use fmt.Sprintf - query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s) %s "+qupdates, Q, mi.table, Q, Q, columns, Q, qmarks, iouStr) + query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s) %s "+qupdates, Q, mi.Table, Q, Q, columns, Q, qmarks, iouStr) d.ins.ReplaceMarks(&query) - if isMulti || !d.ins.HasReturningID(mi, &query) { + if !d.ins.HasReturningID(mi, &query) { res, err := q.ExecContext(ctx, query, values...) if err == nil { - if isMulti { - return res.RowsAffected() - } - lastInsertId, err := res.LastInsertId() if err != nil { - DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) + logs.DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) return lastInsertId, ErrLastInsertIdUnavailable } else { return lastInsertId, nil @@ -613,7 +626,7 @@ func (d *dbBase) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *modelInfo, } // Update execute update sql dbQuerier with given struct reflect.Value. -func (d *dbBase) Update(ctx context.Context, q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) (int64, error) { +func (d *dbBase) Update(ctx context.Context, q dbQuerier, mi *models.ModelInfo, ind reflect.Value, tz *time.Location, cols []string) (int64, error) { pkName, pkValue, ok := getExistPk(mi, ind) if !ok { return 0, ErrMissPK @@ -621,10 +634,10 @@ func (d *dbBase) Update(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref var setNames []string - // if specify cols length is zero, then commit all columns. + // if specify cols length is zero, then commit all Columns. if len(cols) == 0 { - cols = mi.fields.dbcols - setNames = make([]string, 0, len(mi.fields.dbcols)-1) + cols = mi.Fields.DBcols + setNames = make([]string, 0, len(mi.Fields.DBcols)-1) } else { setNames = make([]string, 0, len(cols)) } @@ -637,11 +650,11 @@ func (d *dbBase) Update(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref var findAutoNowAdd, findAutoNow bool var index int for i, col := range setNames { - if mi.fields.GetByColumn(col).autoNowAdd { + if mi.Fields.GetByColumn(col).AutoNowAdd { index = i findAutoNowAdd = true } - if mi.fields.GetByColumn(col).autoNow { + if mi.Fields.GetByColumn(col).AutoNow { findAutoNow = true } } @@ -651,8 +664,8 @@ func (d *dbBase) Update(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref } if !findAutoNow { - for col, info := range mi.fields.columns { - if info.autoNow { + for col, info := range mi.Fields.Columns { + if info.AutoNow { setNames = append(setNames, col) setValues = append(setValues, time.Now()) } @@ -661,14 +674,7 @@ func (d *dbBase) Update(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref setValues = append(setValues, pkValue) - Q := d.ins.TableQuote() - - sep := fmt.Sprintf("%s = ?, %s", Q, Q) - setColumns := strings.Join(setNames, sep) - - query := fmt.Sprintf("UPDATE %s%s%s SET %s%s%s = ? WHERE %s%s%s = ?", Q, mi.table, Q, Q, setColumns, Q, Q, pkName, Q) - - d.ins.ReplaceMarks(&query) + query := d.UpdateSQL(setNames, pkName, mi) res, err := q.ExecContext(ctx, query, setValues...) if err == nil { @@ -677,9 +683,43 @@ func (d *dbBase) Update(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref return 0, err } +func (d *dbBase) UpdateSQL(setNames []string, pkName string, mi *models.ModelInfo) string { + buf := buffers.Get() + defer buffers.Put(buf) + + Q := d.ins.TableQuote() + + _, _ = buf.WriteString("UPDATE ") + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(mi.Table) + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(" SET ") + + for i, name := range setNames { + if i > 0 { + _, _ = buf.WriteString(", ") + } + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(name) + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(" = ?") + } + + _, _ = buf.WriteString(" WHERE ") + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(pkName) + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(" = ?") + + query := buf.String() + d.ins.ReplaceMarks(&query) + + return query +} + // Delete execute delete sql dbQuerier with given struct reflect.Value. // delete index is pk. -func (d *dbBase) Delete(ctx context.Context, q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) (int64, error) { +func (d *dbBase) Delete(ctx context.Context, q dbQuerier, mi *models.ModelInfo, ind reflect.Value, tz *time.Location, cols []string) (int64, error) { var whereCols []string var args []interface{} // if specify cols length > 0, then use it for where condition. @@ -700,14 +740,8 @@ func (d *dbBase) Delete(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref args = append(args, pkValue) } - Q := d.ins.TableQuote() + query := d.DeleteSQL(whereCols, mi) - sep := fmt.Sprintf("%s = ? AND %s", Q, Q) - wheres := strings.Join(whereCols, sep) - - query := fmt.Sprintf("DELETE FROM %s%s%s WHERE %s%s%s = ?", Q, mi.table, Q, Q, wheres, Q) - - d.ins.ReplaceMarks(&query) res, err := q.ExecContext(ctx, query, args...) if err == nil { num, err := res.RowsAffected() @@ -725,16 +759,45 @@ func (d *dbBase) Delete(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref return 0, err } +func (d *dbBase) DeleteSQL(whereCols []string, mi *models.ModelInfo) string { + buf := buffers.Get() + defer buffers.Put(buf) + + Q := d.ins.TableQuote() + + _, _ = buf.WriteString("DELETE FROM ") + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(mi.Table) + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(" WHERE ") + + for i, col := range whereCols { + if i > 0 { + _, _ = buf.WriteString(" AND ") + } + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(col) + _, _ = buf.WriteString(Q) + _, _ = buf.WriteString(" = ?") + } + + query := buf.String() + + d.ins.ReplaceMarks(&query) + + return query +} + // UpdateBatch update table-related record by querySet. // need querySet not struct reflect.Value to update related records. -func (d *dbBase) UpdateBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, params Params, tz *time.Location) (int64, error) { +func (d *dbBase) UpdateBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *models.ModelInfo, cond *Condition, params Params, tz *time.Location) (int64, error) { columns := make([]string, 0, len(params)) values := make([]interface{}, 0, len(params)) for col, val := range params { - if fi, ok := mi.fields.GetByAny(col); !ok || !fi.dbcol { + if fi, ok := mi.Fields.GetByAny(col); !ok || !fi.DBcol { panic(fmt.Errorf("wrong field/column name `%s`", col)) } else { - columns = append(columns, fi.column) + columns = append(columns, fi.Column) values = append(values, val) } } @@ -747,7 +810,7 @@ func (d *dbBase) UpdateBatch(ctx context.Context, q dbQuerier, qs *querySet, mi var specifyIndexes string if qs != nil { tables.parseRelated(qs.related, qs.relDepth) - specifyIndexes = tables.getIndexSql(mi.table, qs.useIndex, qs.indexes) + specifyIndexes = tables.getIndexSql(mi.Table, qs.useIndex, qs.indexes) } where, args := tables.getCondSQL(cond, false, tz) @@ -798,13 +861,13 @@ func (d *dbBase) UpdateBatch(ctx context.Context, q dbQuerier, qs *querySet, mi sets := strings.Join(cols, ", ") + " " if d.ins.SupportUpdateJoin() { - query = fmt.Sprintf("UPDATE %s%s%s T0 %s%sSET %s%s", Q, mi.table, Q, specifyIndexes, join, sets, where) + query = fmt.Sprintf("UPDATE %s%s%s T0 %s%sSET %s%s", Q, mi.Table, Q, specifyIndexes, join, sets, where) } else { supQuery := fmt.Sprintf("SELECT T0.%s%s%s FROM %s%s%s T0 %s%s%s", - Q, mi.fields.pk.column, Q, - Q, mi.table, Q, + Q, mi.Fields.Pk.Column, Q, + Q, mi.Table, Q, specifyIndexes, join, where) - query = fmt.Sprintf("UPDATE %s%s%s SET %sWHERE %s%s%s IN ( %s )", Q, mi.table, Q, sets, Q, mi.fields.pk.column, Q, supQuery) + query = fmt.Sprintf("UPDATE %s%s%s SET %sWHERE %s%s%s IN ( %s )", Q, mi.Table, Q, sets, Q, mi.Fields.Pk.Column, Q, supQuery) } d.ins.ReplaceMarks(&query) @@ -817,41 +880,41 @@ func (d *dbBase) UpdateBatch(ctx context.Context, q dbQuerier, qs *querySet, mi // delete related records. // do UpdateBanch or DeleteBanch by condition of tables' relationship. -func (d *dbBase) deleteRels(ctx context.Context, q dbQuerier, mi *modelInfo, args []interface{}, tz *time.Location) error { - for _, fi := range mi.fields.fieldsReverse { - fi = fi.reverseFieldInfo - switch fi.onDelete { - case odCascade: - cond := NewCondition().And(fmt.Sprintf("%s__in", fi.name), args...) - _, err := d.DeleteBatch(ctx, q, nil, fi.mi, cond, tz) +func (d *dbBase) deleteRels(ctx context.Context, q dbQuerier, mi *models.ModelInfo, args []interface{}, tz *time.Location) error { + for _, fi := range mi.Fields.FieldsReverse { + fi = fi.ReverseFieldInfo + switch fi.OnDelete { + case models.OdCascade: + cond := NewCondition().And(fmt.Sprintf("%s__in", fi.Name), args...) + _, err := d.DeleteBatch(ctx, q, nil, fi.Mi, cond, tz) if err != nil { return err } - case odSetDefault, odSetNULL: - cond := NewCondition().And(fmt.Sprintf("%s__in", fi.name), args...) - params := Params{fi.column: nil} - if fi.onDelete == odSetDefault { - params[fi.column] = fi.initial.String() + case models.OdSetDefault, models.OdSetNULL: + cond := NewCondition().And(fmt.Sprintf("%s__in", fi.Name), args...) + params := Params{fi.Column: nil} + if fi.OnDelete == models.OdSetDefault { + params[fi.Column] = fi.Initial.String() } - _, err := d.UpdateBatch(ctx, q, nil, fi.mi, cond, params, tz) + _, err := d.UpdateBatch(ctx, q, nil, fi.Mi, cond, params, tz) if err != nil { return err } - case odDoNothing: + case models.OdDoNothing: } } return nil } // DeleteBatch delete table-related records. -func (d *dbBase) DeleteBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, tz *time.Location) (int64, error) { +func (d *dbBase) DeleteBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *models.ModelInfo, cond *Condition, tz *time.Location) (int64, error) { tables := newDbTables(mi, d.ins) tables.skipEnd = true var specifyIndexes string if qs != nil { tables.parseRelated(qs.related, qs.relDepth) - specifyIndexes = tables.getIndexSql(mi.table, qs.useIndex, qs.indexes) + specifyIndexes = tables.getIndexSql(mi.Table, qs.useIndex, qs.indexes) } if cond == nil || cond.IsEmpty() { @@ -863,8 +926,8 @@ func (d *dbBase) DeleteBatch(ctx context.Context, q dbQuerier, qs *querySet, mi where, args := tables.getCondSQL(cond, false, tz) join := tables.getJoinSQL() - cols := fmt.Sprintf("T0.%s%s%s", Q, mi.fields.pk.column, Q) - query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s%s", cols, Q, mi.table, Q, specifyIndexes, join, where) + cols := fmt.Sprintf("T0.%s%s%s", Q, mi.Fields.Pk.Column, Q) + query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s%s", cols, Q, mi.Table, Q, specifyIndexes, join, where) d.ins.ReplaceMarks(&query) @@ -883,7 +946,7 @@ func (d *dbBase) DeleteBatch(ctx context.Context, q dbQuerier, qs *querySet, mi if err := rs.Scan(&ref); err != nil { return 0, err } - pkValue, err := d.convertValueFromDB(mi.fields.pk, reflect.ValueOf(ref).Interface(), tz) + pkValue, err := d.convertValueFromDB(mi.Fields.Pk, reflect.ValueOf(ref).Interface(), tz) if err != nil { return 0, err } @@ -891,6 +954,10 @@ func (d *dbBase) DeleteBatch(ctx context.Context, q dbQuerier, qs *querySet, mi cnt++ } + if err = rs.Err(); err != nil { + return 0, err + } + if cnt == 0 { return 0, nil } @@ -900,7 +967,7 @@ func (d *dbBase) DeleteBatch(ctx context.Context, q dbQuerier, qs *querySet, mi marks[i] = "?" } sqlIn := fmt.Sprintf("IN (%s)", strings.Join(marks, ", ")) - query = fmt.Sprintf("DELETE FROM %s%s%s WHERE %s%s%s %s", Q, mi.table, Q, Q, mi.fields.pk.column, Q, sqlIn) + query = fmt.Sprintf("DELETE FROM %s%s%s WHERE %s%s%s %s", Q, mi.Table, Q, Q, mi.Fields.Pk.Column, Q, sqlIn) d.ins.ReplaceMarks(&query) res, err := q.ExecContext(ctx, query, args...) @@ -921,7 +988,7 @@ func (d *dbBase) DeleteBatch(ctx context.Context, q dbQuerier, qs *querySet, mi } // ReadBatch read related records. -func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, container interface{}, tz *time.Location, cols []string) (int64, error) { +func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *models.ModelInfo, cond *Condition, container interface{}, tz *time.Location, cols []string) (int64, error) { val := reflect.ValueOf(container) ind := reflect.Indirect(val) @@ -937,17 +1004,17 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m typ := ind.Type().Elem() switch typ.Kind() { case reflect.Ptr: - fn = getFullName(typ.Elem()) + fn = models.GetFullName(typ.Elem()) case reflect.Struct: isPtr = false - fn = getFullName(typ) - name = getTableName(reflect.New(typ)) + fn = models.GetFullName(typ) + name = models.GetTableName(reflect.New(typ)) } } else { - fn = getFullName(ind.Type()) - name = getTableName(ind) + fn = models.GetFullName(ind.Type()) + name = models.GetTableName(ind) } - unregister = fn != mi.fullName + unregister = fn != mi.FullName } if unregister { @@ -968,26 +1035,26 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m maps = make(map[string]bool) } for _, col := range cols { - if fi, ok := mi.fields.GetByAny(col); ok { - tCols = append(tCols, fi.column) + if fi, ok := mi.Fields.GetByAny(col); ok { + tCols = append(tCols, fi.Column) if hasRel { - maps[fi.column] = true + maps[fi.Column] = true } } else { return 0, fmt.Errorf("wrong field/column name `%s`", col) } } if hasRel { - for _, fi := range mi.fields.fieldsDB { - if fi.fieldType&IsRelField > 0 { - if !maps[fi.column] { - tCols = append(tCols, fi.column) + for _, fi := range mi.Fields.FieldsDB { + if fi.FieldType&IsRelField > 0 { + if !maps[fi.Column] { + tCols = append(tCols, fi.Column) } } } } } else { - tCols = mi.fields.dbcols + tCols = mi.Fields.DBcols } colsNum := len(tCols) @@ -1002,13 +1069,13 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m orderBy := tables.getOrderSQL(qs.orders) limit := tables.getLimitSQL(mi, offset, rlimit) join := tables.getJoinSQL() - specifyIndexes := tables.getIndexSql(mi.table, qs.useIndex, qs.indexes) + specifyIndexes := tables.getIndexSql(mi.Table, qs.useIndex, qs.indexes) for _, tbl := range tables.tables { if tbl.sel { - colsNum += len(tbl.mi.fields.dbcols) + colsNum += len(tbl.mi.Fields.DBcols) sep := fmt.Sprintf("%s, %s.%s", Q, tbl.index, Q) - sels += fmt.Sprintf(", %s.%s%s%s", tbl.index, Q, strings.Join(tbl.mi.fields.dbcols, sep), Q) + sels += fmt.Sprintf(", %s.%s%s%s", tbl.index, Q, strings.Join(tbl.mi.Fields.DBcols, sep), Q) } } @@ -1020,7 +1087,7 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m sels = qs.aggregate } query := fmt.Sprintf("%s %s FROM %s%s%s T0 %s%s%s%s%s%s", - sqlSelect, sels, Q, mi.table, Q, + sqlSelect, sels, Q, mi.Table, Q, specifyIndexes, join, where, groupBy, orderBy, limit) if qs.forUpdate { @@ -1039,7 +1106,7 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m slice := ind if unregister { mi, _ = defaultModelCache.get(name) - tCols = mi.fields.dbcols + tCols = mi.Fields.DBcols colsNum = len(tCols) } @@ -1055,11 +1122,11 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m return 0, err } - elm := reflect.New(mi.addrField.Elem().Type()) + elm := reflect.New(mi.AddrField.Elem().Type()) mind := reflect.Indirect(elm) cacheV := make(map[string]*reflect.Value) - cacheM := make(map[string]*modelInfo) + cacheM := make(map[string]*models.ModelInfo) trefs := refs d.setColsValues(mi, &mind, tCols, refs[:len(tCols)], tz) @@ -1078,18 +1145,18 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m last = *val mmi = cacheM[names] } else { - fi := mmi.fields.GetByName(name) + fi := mmi.Fields.GetByName(name) lastm := mmi - mmi = fi.relModelInfo + mmi = fi.RelModelInfo field := last if last.Kind() != reflect.Invalid { - field = reflect.Indirect(last.FieldByIndex(fi.fieldIndex)) + field = reflect.Indirect(last.FieldByIndex(fi.FieldIndex)) if field.IsValid() { - d.setColsValues(mmi, &field, mmi.fields.dbcols, trefs[:len(mmi.fields.dbcols)], tz) - for _, fi := range mmi.fields.fieldsReverse { - if fi.inModel && fi.reverseFieldInfo.mi == lastm { - if fi.reverseFieldInfo != nil { - f := field.FieldByIndex(fi.fieldIndex) + d.setColsValues(mmi, &field, mmi.Fields.DBcols, trefs[:len(mmi.Fields.DBcols)], tz) + for _, fi := range mmi.Fields.FieldsReverse { + if fi.InModel && fi.ReverseFieldInfo.Mi == lastm { + if fi.ReverseFieldInfo != nil { + f := field.FieldByIndex(fi.FieldIndex) if f.Kind() == reflect.Ptr { f.Set(last.Addr()) } @@ -1103,7 +1170,7 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m cacheM[names] = mmi } } - trefs = trefs[len(mmi.fields.dbcols):] + trefs = trefs[len(mmi.Fields.DBcols):] } } @@ -1130,6 +1197,10 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m cnt++ } + if err = rs.Err(); err != nil { + return 0, err + } + if !one { if cnt > 0 { ind.Set(slice) @@ -1146,7 +1217,7 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m } // Count excute count sql and return count result int64. -func (d *dbBase) Count(ctx context.Context, q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, tz *time.Location) (cnt int64, err error) { +func (d *dbBase) Count(ctx context.Context, q dbQuerier, qs *querySet, mi *models.ModelInfo, cond *Condition, tz *time.Location) (cnt int64, err error) { tables := newDbTables(mi, d.ins) tables.parseRelated(qs.related, qs.relDepth) @@ -1154,12 +1225,12 @@ func (d *dbBase) Count(ctx context.Context, q dbQuerier, qs *querySet, mi *model groupBy := tables.getGroupSQL(qs.groups) tables.getOrderSQL(qs.orders) join := tables.getJoinSQL() - specifyIndexes := tables.getIndexSql(mi.table, qs.useIndex, qs.indexes) + specifyIndexes := tables.getIndexSql(mi.Table, qs.useIndex, qs.indexes) Q := d.ins.TableQuote() query := fmt.Sprintf("SELECT COUNT(*) FROM %s%s%s T0 %s%s%s%s", - Q, mi.table, Q, + Q, mi.Table, Q, specifyIndexes, join, where, groupBy) if groupBy != "" { @@ -1174,7 +1245,7 @@ func (d *dbBase) Count(ctx context.Context, q dbQuerier, qs *querySet, mi *model } // GenerateOperatorSQL generate sql with replacing operator string placeholders and replaced values. -func (d *dbBase) GenerateOperatorSQL(mi *modelInfo, fi *fieldInfo, operator string, args []interface{}, tz *time.Location) (string, []interface{}) { +func (d *dbBase) GenerateOperatorSQL(mi *models.ModelInfo, fi *models.FieldInfo, operator string, args []interface{}, tz *time.Location) (string, []interface{}) { var sql string params := getFlatParams(fi, args, tz) @@ -1206,7 +1277,7 @@ func (d *dbBase) GenerateOperatorSQL(mi *modelInfo, fi *fieldInfo, operator stri params[0] = "IS NULL" } case "iexact", "contains", "icontains", "startswith", "endswith", "istartswith", "iendswith": - param := strings.Replace(ToStr(arg), `%`, `\%`, -1) + param := strings.Replace(utils.ToStr(arg), `%`, `\%`, -1) switch operator { case "iexact": case "contains", "icontains": @@ -1234,18 +1305,18 @@ func (d *dbBase) GenerateOperatorSQL(mi *modelInfo, fi *fieldInfo, operator stri } // GenerateOperatorLeftCol gernerate sql string with inner function, such as UPPER(text). -func (d *dbBase) GenerateOperatorLeftCol(*fieldInfo, string, *string) { +func (d *dbBase) GenerateOperatorLeftCol(*models.FieldInfo, string, *string) { // default not use } // set values to struct column. -func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, values []interface{}, tz *time.Location) { +func (d *dbBase) setColsValues(mi *models.ModelInfo, ind *reflect.Value, cols []string, values []interface{}, tz *time.Location) { for i, column := range cols { val := reflect.Indirect(reflect.ValueOf(values[i])).Interface() - fi := mi.fields.GetByColumn(column) + fi := mi.Fields.GetByColumn(column) - field := ind.FieldByIndex(fi.fieldIndex) + field := ind.FieldByIndex(fi.FieldIndex) value, err := d.convertValueFromDB(fi, val, tz) if err != nil { @@ -1261,7 +1332,7 @@ func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, } // convert value from database result to value following in field type. -func (d *dbBase) convertValueFromDB(fi *fieldInfo, val interface{}, tz *time.Location) (interface{}, error) { +func (d *dbBase) convertValueFromDB(fi *models.FieldInfo, val interface{}, tz *time.Location) (interface{}, error) { if val == nil { return nil, nil } @@ -1269,17 +1340,17 @@ func (d *dbBase) convertValueFromDB(fi *fieldInfo, val interface{}, tz *time.Loc var value interface{} var tErr error - var str *StrTo + var str *utils.StrTo switch v := val.(type) { case []byte: - s := StrTo(string(v)) + s := utils.StrTo(string(v)) str = &s case string: - s := StrTo(v) + s := utils.StrTo(v) str = &s } - fieldType := fi.fieldType + fieldType := fi.FieldType setValue: switch { @@ -1290,7 +1361,7 @@ setValue: b := v == 1 value = b default: - s := StrTo(ToStr(v)) + s := utils.StrTo(utils.ToStr(v)) str = &s } } @@ -1304,7 +1375,7 @@ setValue: } case fieldType == TypeVarCharField || fieldType == TypeCharField || fieldType == TypeTextField || fieldType == TypeJSONField || fieldType == TypeJsonbField: if str == nil { - value = ToStr(val) + value = utils.ToStr(val) } else { value = str.String() } @@ -1315,7 +1386,7 @@ setValue: d.ins.TimeFromDB(&t, tz) value = t default: - s := StrTo(ToStr(t)) + s := utils.StrTo(utils.ToStr(t)) str = &s } } @@ -1326,25 +1397,25 @@ setValue: err error ) - if fi.timePrecision != nil && len(s) >= (20+*fi.timePrecision) { - layout := formatDateTime + "." - for i := 0; i < *fi.timePrecision; i++ { + if fi.TimePrecision != nil && len(s) >= (20+*fi.TimePrecision) { + layout := utils.FormatDateTime + "." + for i := 0; i < *fi.TimePrecision; i++ { layout += "0" } - t, err = time.ParseInLocation(layout, s[:20+*fi.timePrecision], tz) + t, err = time.ParseInLocation(layout, s[:20+*fi.TimePrecision], tz) } else if len(s) >= 19 { s = s[:19] - t, err = time.ParseInLocation(formatDateTime, s, tz) + t, err = time.ParseInLocation(utils.FormatDateTime, s, tz) } else if len(s) >= 10 { if len(s) > 10 { s = s[:10] } - t, err = time.ParseInLocation(formatDate, s, tz) + t, err = time.ParseInLocation(utils.FormatDate, s, tz) } else if len(s) >= 8 { if len(s) > 8 { s = s[:8] } - t, err = time.ParseInLocation(formatTime, s, tz) + t, err = time.ParseInLocation(utils.FormatTime, s, tz) } t = t.In(DefaultTimeLoc) @@ -1356,7 +1427,7 @@ setValue: } case fieldType&IsIntegerField > 0: if str == nil { - s := StrTo(ToStr(val)) + s := utils.StrTo(utils.ToStr(val)) str = &s } if str != nil { @@ -1397,7 +1468,7 @@ setValue: case float64: value = v default: - s := StrTo(ToStr(v)) + s := utils.StrTo(utils.ToStr(v)) str = &s } } @@ -1410,14 +1481,14 @@ setValue: value = v } case fieldType&IsRelField > 0: - fi = fi.relModelInfo.fields.pk - fieldType = fi.fieldType + fi = fi.RelModelInfo.Fields.Pk + fieldType = fi.FieldType goto setValue } end: if tErr != nil { - err := fmt.Errorf("convert to `%s` failed, field: %s err: %s", fi.addrValue.Type(), fi.fullName, tErr) + err := fmt.Errorf("convert to `%s` failed, field: %s err: %s", fi.AddrValue.Type(), fi.FullName, tErr) return nil, err } @@ -1425,9 +1496,9 @@ end: } // set one value to struct column field. -func (d *dbBase) setFieldValue(fi *fieldInfo, value interface{}, field reflect.Value) (interface{}, error) { - fieldType := fi.fieldType - isNative := !fi.isFielder +func (d *dbBase) setFieldValue(fi *models.FieldInfo, value interface{}, field reflect.Value) (interface{}, error) { + fieldType := fi.FieldType + isNative := !fi.IsFielder setValue: switch { @@ -1594,20 +1665,20 @@ setValue: } case fieldType&IsRelField > 0: if value != nil { - fieldType = fi.relModelInfo.fields.pk.fieldType - mf := reflect.New(fi.relModelInfo.addrField.Elem().Type()) + fieldType = fi.RelModelInfo.Fields.Pk.FieldType + mf := reflect.New(fi.RelModelInfo.AddrField.Elem().Type()) field.Set(mf) - f := mf.Elem().FieldByIndex(fi.relModelInfo.fields.pk.fieldIndex) + f := mf.Elem().FieldByIndex(fi.RelModelInfo.Fields.Pk.FieldIndex) field = f goto setValue } } if !isNative { - fd := field.Addr().Interface().(Fielder) + fd := field.Addr().Interface().(models.Fielder) err := fd.SetRaw(value) if err != nil { - err = fmt.Errorf("converted value `%v` set to Fielder `%s` failed, err: %s", value, fi.fullName, err) + err = fmt.Errorf("converted value `%v` set to Fielder `%s` failed, err: %s", value, fi.FullName, err) return nil, err } } @@ -1616,7 +1687,7 @@ setValue: } // ReadValues query sql, read values , save to *[]ParamList. -func (d *dbBase) ReadValues(ctx context.Context, q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, exprs []string, container interface{}, tz *time.Location) (int64, error) { +func (d *dbBase) ReadValues(ctx context.Context, q dbQuerier, qs *querySet, mi *models.ModelInfo, cond *Condition, exprs []string, container interface{}, tz *time.Location) (int64, error) { var ( maps []Params lists []ParamsList @@ -1651,7 +1722,7 @@ func (d *dbBase) ReadValues(ctx context.Context, q dbQuerier, qs *querySet, mi * var ( cols []string - infos []*fieldInfo + infos []*models.FieldInfo ) hasExprs := len(exprs) > 0 @@ -1660,20 +1731,20 @@ func (d *dbBase) ReadValues(ctx context.Context, q dbQuerier, qs *querySet, mi * if hasExprs { cols = make([]string, 0, len(exprs)) - infos = make([]*fieldInfo, 0, len(exprs)) + infos = make([]*models.FieldInfo, 0, len(exprs)) for _, ex := range exprs { index, name, fi, suc := tables.parseExprs(mi, strings.Split(ex, ExprSep)) if !suc { panic(fmt.Errorf("unknown field/column name `%s`", ex)) } - cols = append(cols, fmt.Sprintf("%s.%s%s%s %s%s%s", index, Q, fi.column, Q, Q, name, Q)) + cols = append(cols, fmt.Sprintf("%s.%s%s%s %s%s%s", index, Q, fi.Column, Q, Q, name, Q)) infos = append(infos, fi) } } else { - cols = make([]string, 0, len(mi.fields.dbcols)) - infos = make([]*fieldInfo, 0, len(exprs)) - for _, fi := range mi.fields.fieldsDB { - cols = append(cols, fmt.Sprintf("T0.%s%s%s %s%s%s", Q, fi.column, Q, Q, fi.name, Q)) + cols = make([]string, 0, len(mi.Fields.DBcols)) + infos = make([]*models.FieldInfo, 0, len(exprs)) + for _, fi := range mi.Fields.FieldsDB { + cols = append(cols, fmt.Sprintf("T0.%s%s%s %s%s%s", Q, fi.Column, Q, Q, fi.Name, Q)) infos = append(infos, fi) } } @@ -1683,7 +1754,7 @@ func (d *dbBase) ReadValues(ctx context.Context, q dbQuerier, qs *querySet, mi * orderBy := tables.getOrderSQL(qs.orders) limit := tables.getLimitSQL(mi, qs.offset, qs.limit) join := tables.getJoinSQL() - specifyIndexes := tables.getIndexSql(mi.table, qs.useIndex, qs.indexes) + specifyIndexes := tables.getIndexSql(mi.Table, qs.useIndex, qs.indexes) sels := strings.Join(cols, ", ") @@ -1693,7 +1764,7 @@ func (d *dbBase) ReadValues(ctx context.Context, q dbQuerier, qs *querySet, mi * } query := fmt.Sprintf("%s %s FROM %s%s%s T0 %s%s%s%s%s%s", sqlSelect, sels, - Q, mi.table, Q, + Q, mi.Table, Q, specifyIndexes, join, where, groupBy, orderBy, limit) d.ins.ReplaceMarks(&query) @@ -1776,6 +1847,10 @@ func (d *dbBase) ReadValues(ctx context.Context, q dbQuerier, qs *querySet, mi * cnt++ } + if err = rs.Err(); err != nil { + return 0, err + } + switch v := container.(type) { case *[]Params: *v = maps @@ -1808,12 +1883,12 @@ func (d *dbBase) ReplaceMarks(query *string) { } // flag of RETURNING sql. -func (d *dbBase) HasReturningID(*modelInfo, *string) bool { +func (d *dbBase) HasReturningID(*models.ModelInfo, *string) bool { return false } // sync auto key -func (d *dbBase) setval(ctx context.Context, db dbQuerier, mi *modelInfo, autoFields []string) error { +func (d *dbBase) setval(ctx context.Context, db dbQuerier, mi *models.ModelInfo, autoFields []string) error { return nil } @@ -1854,7 +1929,7 @@ func (d *dbBase) GetTables(db dbQuerier) (map[string]bool, error) { } } - return tables, nil + return tables, rows.Err() } // GetColumns get all cloumns in table. @@ -1881,7 +1956,7 @@ func (d *dbBase) GetColumns(ctx context.Context, db dbQuerier, table string) (ma columns[name] = [3]string{name, typ, null} } - return columns, nil + return columns, rows.Err() } // not implement. @@ -1923,7 +1998,7 @@ func (d *dbBase) GenerateSpecifyIndex(tableName string, useIndex int, indexes [] case hints.KeyIgnoreIndex: useWay = `IGNORE` default: - DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") + logs.DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") return `` } diff --git a/client/orm/db_alias.go b/client/orm/db_alias.go index 28c8ab8e..ff0b962f 100644 --- a/client/orm/db_alias.go +++ b/client/orm/db_alias.go @@ -21,6 +21,8 @@ import ( "sync" "time" + "github.com/beego/beego/v2/client/orm/internal/logs" + lru "github.com/hashicorp/golang-lru" ) @@ -320,7 +322,7 @@ func detectTZ(al *alias) { al.TZ = t.Location() } } else { - DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error()) + logs.DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error()) } } @@ -347,7 +349,7 @@ func detectTZ(al *alias) { if err == nil { al.TZ = loc } else { - DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error()) + logs.DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error()) } } } @@ -479,7 +481,7 @@ end: if db != nil { db.Close() } - DebugLog.Println(err.Error()) + logs.DebugLog.Println(err.Error()) } return err diff --git a/client/orm/db_mysql.go b/client/orm/db_mysql.go index 75d24b2a..889d807f 100644 --- a/client/orm/db_mysql.go +++ b/client/orm/db_mysql.go @@ -19,6 +19,10 @@ import ( "fmt" "reflect" "strings" + + "github.com/beego/beego/v2/client/orm/internal/logs" + + "github.com/beego/beego/v2/client/orm/internal/models" ) // mysql operators. @@ -72,28 +76,28 @@ type dbBaseMysql struct { var _ dbBaser = new(dbBaseMysql) -// get mysql operator. +// OperatorSQL get mysql operator. func (d *dbBaseMysql) OperatorSQL(operator string) string { return mysqlOperators[operator] } -// get mysql table field types. +// DbTypes get mysql table field types. func (d *dbBaseMysql) DbTypes() map[string]string { return mysqlTypes } -// show table sql for mysql. +// ShowTablesQuery show table sql for mysql. func (d *dbBaseMysql) ShowTablesQuery() string { return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema = DATABASE()" } -// show columns sql of table for mysql. +// ShowColumnsQuery show Columns sql of table for mysql. func (d *dbBaseMysql) ShowColumnsQuery(table string) string { - return fmt.Sprintf("SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE FROM information_schema.columns "+ + return fmt.Sprintf("SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE FROM information_schema.Columns "+ "WHERE table_schema = DATABASE() AND table_name = '%s'", table) } -// execute sql to check index exist. +// IndexExists execute sql to check index exist. func (d *dbBaseMysql) IndexExists(ctx context.Context, db dbQuerier, table string, name string) bool { row := db.QueryRowContext(ctx, "SELECT count(*) FROM information_schema.statistics "+ "WHERE table_schema = DATABASE() AND table_name = ? AND index_name = ?", table, name) @@ -106,7 +110,7 @@ func (d *dbBaseMysql) IndexExists(ctx context.Context, db dbQuerier, table strin // If your primary key or unique column conflict will update // If no will insert // Add "`" for mysql sql building -func (d *dbBaseMysql) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *modelInfo, ind reflect.Value, a *alias, args ...string) (int64, error) { +func (d *dbBaseMysql) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *models.ModelInfo, ind reflect.Value, a *alias, args ...string) (int64, error) { var iouStr string argsMap := map[string]string{} @@ -120,10 +124,9 @@ func (d *dbBaseMysql) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *model } } - isMulti := false - names := make([]string, 0, len(mi.fields.dbcols)-1) + names := make([]string, 0, len(mi.Fields.DBcols)-1) Q := d.ins.TableQuote() - values, _, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, &names, a.TZ) + values, _, err := d.collectValues(mi, ind, mi.Fields.DBcols, true, true, &names, a.TZ) if err != nil { return 0, err } @@ -150,26 +153,17 @@ func (d *dbBaseMysql) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *model qupdates := strings.Join(updates, ", ") columns := strings.Join(names, sep) - multi := len(values) / len(names) - - if isMulti { - qmarks = strings.Repeat(qmarks+"), (", multi-1) + qmarks - } // conflitValue maybe is an int,can`t use fmt.Sprintf - query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s) %s "+qupdates, Q, mi.table, Q, Q, columns, Q, qmarks, iouStr) + query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s) %s "+qupdates, Q, mi.Table, Q, Q, columns, Q, qmarks, iouStr) d.ins.ReplaceMarks(&query) - if isMulti || !d.ins.HasReturningID(mi, &query) { + if !d.ins.HasReturningID(mi, &query) { res, err := q.ExecContext(ctx, query, values...) if err == nil { - if isMulti { - return res.RowsAffected() - } - lastInsertId, err := res.LastInsertId() if err != nil { - DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) + logs.DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) return lastInsertId, ErrLastInsertIdUnavailable } else { return lastInsertId, nil diff --git a/client/orm/db_oracle.go b/client/orm/db_oracle.go index a3b93ff3..5057f358 100644 --- a/client/orm/db_oracle.go +++ b/client/orm/db_oracle.go @@ -19,6 +19,10 @@ import ( "fmt" "strings" + "github.com/beego/beego/v2/client/orm/internal/logs" + + "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/beego/beego/v2/client/orm/hints" ) @@ -116,16 +120,16 @@ func (d *dbBaseOracle) GenerateSpecifyIndex(tableName string, useIndex int, inde case hints.KeyIgnoreIndex: hint = `NO_INDEX` default: - DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") + logs.DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") return `` } return fmt.Sprintf(` /*+ %s(%s %s)*/ `, hint, tableName, strings.Join(s, `,`)) } -// execute insert sql with given struct and given values. +// InsertValue execute insert sql with given struct and given values. // insert the given values, not the field values in struct. -func (d *dbBaseOracle) InsertValue(ctx context.Context, q dbQuerier, mi *modelInfo, isMulti bool, names []string, values []interface{}) (int64, error) { +func (d *dbBaseOracle) InsertValue(ctx context.Context, q dbQuerier, mi *models.ModelInfo, isMulti bool, names []string, values []interface{}) (int64, error) { Q := d.ins.TableQuote() marks := make([]string, len(names)) @@ -143,7 +147,7 @@ func (d *dbBaseOracle) InsertValue(ctx context.Context, q dbQuerier, mi *modelIn qmarks = strings.Repeat(qmarks+"), (", multi-1) + qmarks } - query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s)", Q, mi.table, Q, Q, columns, Q, qmarks) + query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s)", Q, mi.Table, Q, Q, columns, Q, qmarks) d.ins.ReplaceMarks(&query) @@ -156,7 +160,7 @@ func (d *dbBaseOracle) InsertValue(ctx context.Context, q dbQuerier, mi *modelIn lastInsertId, err := res.LastInsertId() if err != nil { - DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) + logs.DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) return lastInsertId, ErrLastInsertIdUnavailable } else { return lastInsertId, nil diff --git a/client/orm/db_postgres.go b/client/orm/db_postgres.go index b2f321db..b52b2578 100644 --- a/client/orm/db_postgres.go +++ b/client/orm/db_postgres.go @@ -18,6 +18,10 @@ import ( "context" "fmt" "strconv" + + "github.com/beego/beego/v2/client/orm/internal/logs" + + "github.com/beego/beego/v2/client/orm/internal/models" ) // postgresql operators. @@ -76,7 +80,7 @@ func (d *dbBasePostgres) OperatorSQL(operator string) string { } // generate functioned sql string, such as contains(text). -func (d *dbBasePostgres) GenerateOperatorLeftCol(fi *fieldInfo, operator string, leftCol *string) { +func (d *dbBasePostgres) GenerateOperatorLeftCol(fi *models.FieldInfo, operator string, leftCol *string) { switch operator { case "contains", "startswith", "endswith": *leftCol = fmt.Sprintf("%s::text", *leftCol) @@ -128,20 +132,20 @@ func (d *dbBasePostgres) ReplaceMarks(query *string) { } // make returning sql support for postgresql. -func (d *dbBasePostgres) HasReturningID(mi *modelInfo, query *string) bool { - fi := mi.fields.pk - if fi.fieldType&IsPositiveIntegerField == 0 && fi.fieldType&IsIntegerField == 0 { +func (d *dbBasePostgres) HasReturningID(mi *models.ModelInfo, query *string) bool { + fi := mi.Fields.Pk + if fi.FieldType&IsPositiveIntegerField == 0 && fi.FieldType&IsIntegerField == 0 { return false } if query != nil { - *query = fmt.Sprintf(`%s RETURNING "%s"`, *query, fi.column) + *query = fmt.Sprintf(`%s RETURNING "%s"`, *query, fi.Column) } return true } // sync auto key -func (d *dbBasePostgres) setval(ctx context.Context, db dbQuerier, mi *modelInfo, autoFields []string) error { +func (d *dbBasePostgres) setval(ctx context.Context, db dbQuerier, mi *models.ModelInfo, autoFields []string) error { if len(autoFields) == 0 { return nil } @@ -149,9 +153,9 @@ func (d *dbBasePostgres) setval(ctx context.Context, db dbQuerier, mi *modelInfo Q := d.ins.TableQuote() for _, name := range autoFields { query := fmt.Sprintf("SELECT setval(pg_get_serial_sequence('%s', '%s'), (SELECT MAX(%s%s%s) FROM %s%s%s));", - mi.table, name, + mi.Table, name, Q, name, Q, - Q, mi.table, Q) + Q, mi.Table, Q) if _, err := db.ExecContext(ctx, query); err != nil { return err } @@ -164,9 +168,9 @@ func (d *dbBasePostgres) ShowTablesQuery() string { return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')" } -// show table columns sql for postgresql. +// show table Columns sql for postgresql. func (d *dbBasePostgres) ShowColumnsQuery(table string) string { - return fmt.Sprintf("SELECT column_name, data_type, is_nullable FROM information_schema.columns where table_schema NOT IN ('pg_catalog', 'information_schema') and table_name = '%s'", table) + return fmt.Sprintf("SELECT column_name, data_type, is_nullable FROM information_schema.Columns where table_schema NOT IN ('pg_catalog', 'information_schema') and table_name = '%s'", table) } // get column types of postgresql. @@ -185,7 +189,7 @@ func (d *dbBasePostgres) IndexExists(ctx context.Context, db dbQuerier, table st // GenerateSpecifyIndex return a specifying index clause func (d *dbBasePostgres) GenerateSpecifyIndex(tableName string, useIndex int, indexes []string) string { - DebugLog.Println("[WARN] Not support any specifying index action, so that action is ignored") + logs.DebugLog.Println("[WARN] Not support any specifying index action, so that action is ignored") return `` } diff --git a/client/orm/db_sqlite.go b/client/orm/db_sqlite.go index 6a4b3131..8041f7be 100644 --- a/client/orm/db_sqlite.go +++ b/client/orm/db_sqlite.go @@ -22,6 +22,10 @@ import ( "strings" "time" + "github.com/beego/beego/v2/client/orm/internal/logs" + + "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/beego/beego/v2/client/orm/hints" ) @@ -74,9 +78,9 @@ type dbBaseSqlite struct { var _ dbBaser = new(dbBaseSqlite) // override base db read for update behavior as SQlite does not support syntax -func (d *dbBaseSqlite) Read(ctx context.Context, q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string, isForUpdate bool) error { +func (d *dbBaseSqlite) Read(ctx context.Context, q dbQuerier, mi *models.ModelInfo, ind reflect.Value, tz *time.Location, cols []string, isForUpdate bool) error { if isForUpdate { - DebugLog.Println("[WARN] SQLite does not support SELECT FOR UPDATE query, isForUpdate param is ignored and always as false to do the work") + logs.DebugLog.Println("[WARN] SQLite does not support SELECT FOR UPDATE query, isForUpdate param is ignored and always as false to do the work") } return d.dbBase.Read(ctx, q, mi, ind, tz, cols, false) } @@ -88,8 +92,8 @@ func (d *dbBaseSqlite) OperatorSQL(operator string) string { // generate functioned sql for sqlite. // only support DATE(text). -func (d *dbBaseSqlite) GenerateOperatorLeftCol(fi *fieldInfo, operator string, leftCol *string) { - if fi.fieldType == TypeDateField { +func (d *dbBaseSqlite) GenerateOperatorLeftCol(fi *models.FieldInfo, operator string, leftCol *string) { + if fi.FieldType == TypeDateField { *leftCol = fmt.Sprintf("DATE(%s)", *leftCol) } } @@ -114,7 +118,7 @@ func (d *dbBaseSqlite) ShowTablesQuery() string { return "SELECT name FROM sqlite_master WHERE type = 'table'" } -// get columns in sqlite. +// get Columns in sqlite. func (d *dbBaseSqlite) GetColumns(ctx context.Context, db dbQuerier, table string) (map[string][3]string, error) { query := d.ins.ShowColumnsQuery(table) rows, err := db.QueryContext(ctx, query) @@ -132,10 +136,10 @@ func (d *dbBaseSqlite) GetColumns(ctx context.Context, db dbQuerier, table strin columns[name.String] = [3]string{name.String, typ.String, null.String} } - return columns, nil + return columns, rows.Err() } -// get show columns sql in sqlite. +// get show Columns sql in sqlite. func (d *dbBaseSqlite) ShowColumnsQuery(table string) string { return fmt.Sprintf("pragma table_info('%s')", table) } @@ -171,7 +175,7 @@ func (d *dbBaseSqlite) GenerateSpecifyIndex(tableName string, useIndex int, inde case hints.KeyUseIndex, hints.KeyForceIndex: return fmt.Sprintf(` INDEXED BY %s `, strings.Join(s, `,`)) default: - DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") + logs.DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") return `` } } diff --git a/client/orm/db_tables.go b/client/orm/db_tables.go index a0b355ca..9d30afb3 100644 --- a/client/orm/db_tables.go +++ b/client/orm/db_tables.go @@ -19,6 +19,8 @@ import ( "strings" "time" + "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/beego/beego/v2/client/orm/clauses" "github.com/beego/beego/v2/client/orm/clauses/order_clause" ) @@ -31,8 +33,8 @@ type dbTable struct { names []string sel bool inner bool - mi *modelInfo - fi *fieldInfo + mi *models.ModelInfo + fi *models.FieldInfo jtl *dbTable } @@ -40,14 +42,14 @@ type dbTable struct { type dbTables struct { tablesM map[string]*dbTable tables []*dbTable - mi *modelInfo + mi *models.ModelInfo base dbBaser skipEnd bool } // set table info to collection. // if not exist, create new. -func (t *dbTables) set(names []string, mi *modelInfo, fi *fieldInfo, inner bool) *dbTable { +func (t *dbTables) set(names []string, mi *models.ModelInfo, fi *models.FieldInfo, inner bool) *dbTable { name := strings.Join(names, ExprSep) if j, ok := t.tablesM[name]; ok { j.name = name @@ -64,7 +66,7 @@ func (t *dbTables) set(names []string, mi *modelInfo, fi *fieldInfo, inner bool) } // add table info to collection. -func (t *dbTables) add(names []string, mi *modelInfo, fi *fieldInfo, inner bool) (*dbTable, bool) { +func (t *dbTables) add(names []string, mi *models.ModelInfo, fi *models.FieldInfo, inner bool) (*dbTable, bool) { name := strings.Join(names, ExprSep) if _, ok := t.tablesM[name]; !ok { i := len(t.tables) + 1 @@ -82,29 +84,29 @@ func (t *dbTables) get(name string) (*dbTable, bool) { return j, ok } -// get related fields info in recursive depth loop. +// get related Fields info in recursive depth loop. // loop once, depth decreases one. -func (t *dbTables) loopDepth(depth int, prefix string, fi *fieldInfo, related []string) []string { - if depth < 0 || fi.fieldType == RelManyToMany { +func (t *dbTables) loopDepth(depth int, prefix string, fi *models.FieldInfo, related []string) []string { + if depth < 0 || fi.FieldType == RelManyToMany { return related } if prefix == "" { - prefix = fi.name + prefix = fi.Name } else { - prefix = prefix + ExprSep + fi.name + prefix = prefix + ExprSep + fi.Name } related = append(related, prefix) depth-- - for _, fi := range fi.relModelInfo.fields.fieldsRel { + for _, fi := range fi.RelModelInfo.Fields.FieldsRel { related = t.loopDepth(depth, prefix, fi, related) } return related } -// parse related fields. +// parse related Fields. func (t *dbTables) parseRelated(rels []string, depth int) { relsNum := len(rels) related := make([]string, relsNum) @@ -117,7 +119,7 @@ func (t *dbTables) parseRelated(rels []string, depth int) { } relDepth-- - for _, fi := range t.mi.fields.fieldsRel { + for _, fi := range t.mi.Fields.FieldsRel { related = t.loopDepth(relDepth, "", fi, related) } @@ -133,18 +135,18 @@ func (t *dbTables) parseRelated(rels []string, depth int) { inner := true for _, ex := range exs { - if fi, ok := mmi.fields.GetByAny(ex); ok && fi.rel && fi.fieldType != RelManyToMany { - names = append(names, fi.name) - mmi = fi.relModelInfo + if fi, ok := mmi.Fields.GetByAny(ex); ok && fi.Rel && fi.FieldType != RelManyToMany { + names = append(names, fi.Name) + mmi = fi.RelModelInfo - if fi.null || t.skipEnd { + if fi.Null || t.skipEnd { inner = false } jt := t.set(names, mmi, fi, inner) jt.jtl = jtl - if fi.reverse { + if fi.Reverse { cancel = false } @@ -185,24 +187,24 @@ func (t *dbTables) getJoinSQL() (join string) { t1 = jt.jtl.index } t2 = jt.index - table = jt.mi.table + table = jt.mi.Table switch { - case jt.fi.fieldType == RelManyToMany || jt.fi.fieldType == RelReverseMany || jt.fi.reverse && jt.fi.reverseFieldInfo.fieldType == RelManyToMany: - c1 = jt.fi.mi.fields.pk.column - for _, ffi := range jt.mi.fields.fieldsRel { - if jt.fi.mi == ffi.relModelInfo { - c2 = ffi.column + case jt.fi.FieldType == RelManyToMany || jt.fi.FieldType == RelReverseMany || jt.fi.Reverse && jt.fi.ReverseFieldInfo.FieldType == RelManyToMany: + c1 = jt.fi.Mi.Fields.Pk.Column + for _, ffi := range jt.mi.Fields.FieldsRel { + if jt.fi.Mi == ffi.RelModelInfo { + c2 = ffi.Column break } } default: - c1 = jt.fi.column - c2 = jt.fi.relModelInfo.fields.pk.column + c1 = jt.fi.Column + c2 = jt.fi.RelModelInfo.Fields.Pk.Column - if jt.fi.reverse { - c1 = jt.mi.fields.pk.column - c2 = jt.fi.reverseFieldInfo.column + if jt.fi.Reverse { + c1 = jt.mi.Fields.Pk.Column + c2 = jt.fi.ReverseFieldInfo.Column } } @@ -213,11 +215,11 @@ func (t *dbTables) getJoinSQL() (join string) { } // parse orm model struct field tag expression. -func (t *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string, info *fieldInfo, success bool) { +func (t *dbTables) parseExprs(mi *models.ModelInfo, exprs []string) (index, name string, info *models.FieldInfo, success bool) { var ( jtl *dbTable - fi *fieldInfo - fiN *fieldInfo + fi *models.FieldInfo + fiN *models.FieldInfo mmi = mi ) @@ -238,38 +240,38 @@ loopFor: } if i == 0 { - fi, ok = mmi.fields.GetByAny(ex) + fi, ok = mmi.Fields.GetByAny(ex) } _ = okN if ok { - isRel := fi.rel || fi.reverse + isRel := fi.Rel || fi.Reverse - names = append(names, fi.name) + names = append(names, fi.Name) switch { - case fi.rel: - mmi = fi.relModelInfo - if fi.fieldType == RelManyToMany { - mmi = fi.relThroughModelInfo + case fi.Rel: + mmi = fi.RelModelInfo + if fi.FieldType == RelManyToMany { + mmi = fi.RelThroughModelInfo } - case fi.reverse: - mmi = fi.reverseFieldInfo.mi + case fi.Reverse: + mmi = fi.ReverseFieldInfo.Mi } if i < num { - fiN, okN = mmi.fields.GetByAny(exprs[i+1]) + fiN, okN = mmi.Fields.GetByAny(exprs[i+1]) } - if isRel && (!fi.mi.isThrough || num != i) { - if fi.null || t.skipEnd { + if isRel && (!fi.Mi.IsThrough || num != i) { + if fi.Null || t.skipEnd { inner = false } if t.skipEnd && okN || !t.skipEnd { - if t.skipEnd && okN && fiN.pk { + if t.skipEnd && okN && fiN.Pk { goto loopEnd } @@ -295,20 +297,20 @@ loopFor: info = fi if jtl == nil { - name = fi.name + name = fi.Name } else { - name = jtl.name + ExprSep + fi.name + name = jtl.name + ExprSep + fi.Name } switch { - case fi.rel: + case fi.Rel: - case fi.reverse: - switch fi.reverseFieldInfo.fieldType { + case fi.Reverse: + switch fi.ReverseFieldInfo.FieldType { case RelOneToOne, RelForeignKey: index = jtl.index - info = fi.reverseFieldInfo.mi.fields.pk - name = info.name + info = fi.ReverseFieldInfo.Mi.Fields.Pk + name = info.Name } } @@ -382,7 +384,7 @@ func (t *dbTables) getCondSQL(cond *Condition, sub bool, tz *time.Location) (whe operSQL, args = t.base.GenerateOperatorSQL(mi, fi, operator, p.args, tz) } - leftCol := fmt.Sprintf("%s.%s%s%s", index, Q, fi.column, Q) + leftCol := fmt.Sprintf("%s.%s%s%s", index, Q, fi.Column, Q) t.base.GenerateOperatorLeftCol(fi, operator, &leftCol) where += fmt.Sprintf("%s %s ", leftCol, operSQL) @@ -415,7 +417,7 @@ func (t *dbTables) getGroupSQL(groups []string) (groupSQL string) { panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(exprs, ExprSep))) } - groupSqls = append(groupSqls, fmt.Sprintf("%s.%s%s%s", index, Q, fi.column, Q)) + groupSqls = append(groupSqls, fmt.Sprintf("%s.%s%s%s", index, Q, fi.Column, Q)) } groupSQL = fmt.Sprintf("GROUP BY %s ", strings.Join(groupSqls, ", ")) @@ -449,7 +451,7 @@ func (t *dbTables) getOrderSQL(orders []*order_clause.Order) (orderSQL string) { panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(clause, ExprSep))) } - orderSqls = append(orderSqls, fmt.Sprintf("%s.%s%s%s %s", index, Q, fi.column, Q, order.SortString())) + orderSqls = append(orderSqls, fmt.Sprintf("%s.%s%s%s %s", index, Q, fi.Column, Q, order.SortString())) } } @@ -458,7 +460,7 @@ func (t *dbTables) getOrderSQL(orders []*order_clause.Order) (orderSQL string) { } // generate limit sql. -func (t *dbTables) getLimitSQL(mi *modelInfo, offset int64, limit int64) (limits string) { +func (t *dbTables) getLimitSQL(mi *models.ModelInfo, offset int64, limit int64) (limits string) { if limit == 0 { limit = int64(DefaultRowsLimit) } @@ -490,7 +492,7 @@ func (t *dbTables) getIndexSql(tableName string, useIndex int, indexes []string) } // crete new tables collection. -func newDbTables(mi *modelInfo, base dbBaser) *dbTables { +func newDbTables(mi *models.ModelInfo, base dbBaser) *dbTables { tables := &dbTables{} tables.tablesM = make(map[string]*dbTable) tables.mi = mi diff --git a/client/orm/db_test.go b/client/orm/db_test.go new file mode 100644 index 00000000..43fa3798 --- /dev/null +++ b/client/orm/db_test.go @@ -0,0 +1,231 @@ +// Copyright 2020 beego +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package orm + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/beego/beego/v2/client/orm/internal/models" +) + +func TestDbBase_InsertValueSQL(t *testing.T) { + + mi := &models.ModelInfo{ + Table: "test_table", + } + + testCases := []struct { + name string + db *dbBase + isMulti bool + names []string + values []interface{} + + wantRes string + }{ + { + name: "single insert by dbBase", + db: &dbBase{ + ins: &dbBase{}, + }, + isMulti: false, + names: []string{"name", "age"}, + values: []interface{}{"test", 18}, + wantRes: "INSERT INTO `test_table` (`name`, `age`) VALUES (?, ?)", + }, + { + name: "single insert by dbBasePostgres", + db: &dbBase{ + ins: newdbBasePostgres(), + }, + isMulti: false, + names: []string{"name", "age"}, + values: []interface{}{"test", 18}, + wantRes: "INSERT INTO \"test_table\" (\"name\", \"age\") VALUES ($1, $2)", + }, + { + name: "multi insert by dbBase", + db: &dbBase{ + ins: &dbBase{}, + }, + isMulti: true, + names: []string{"name", "age"}, + values: []interface{}{"test", 18, "test2", 19}, + wantRes: "INSERT INTO `test_table` (`name`, `age`) VALUES (?, ?), (?, ?)", + }, + { + name: "multi insert by dbBasePostgres", + db: &dbBase{ + ins: newdbBasePostgres(), + }, + isMulti: true, + names: []string{"name", "age"}, + values: []interface{}{"test", 18, "test2", 19}, + wantRes: "INSERT INTO \"test_table\" (\"name\", \"age\") VALUES ($1, $2), ($3, $4)", + }, + { + name: "multi insert by dbBase but values is not enough", + db: &dbBase{ + ins: &dbBase{}, + }, + isMulti: true, + names: []string{"name", "age"}, + values: []interface{}{"test", 18, "test2"}, + wantRes: "INSERT INTO `test_table` (`name`, `age`) VALUES (?, ?)", + }, + { + name: "multi insert by dbBasePostgres but values is not enough", + db: &dbBase{ + ins: newdbBasePostgres(), + }, + isMulti: true, + names: []string{"name", "age"}, + values: []interface{}{"test", 18, "test2"}, + wantRes: "INSERT INTO \"test_table\" (\"name\", \"age\") VALUES ($1, $2)", + }, + { + name: "single insert by dbBase but values is double to names", + db: &dbBase{ + ins: &dbBase{}, + }, + isMulti: false, + names: []string{"name", "age"}, + values: []interface{}{"test", 18, "test2", 19}, + wantRes: "INSERT INTO `test_table` (`name`, `age`) VALUES (?, ?)", + }, + { + name: "single insert by dbBasePostgres but values is double to names", + db: &dbBase{ + ins: newdbBasePostgres(), + }, + isMulti: false, + names: []string{"name", "age"}, + values: []interface{}{"test", 18, "test2", 19}, + wantRes: "INSERT INTO \"test_table\" (\"name\", \"age\") VALUES ($1, $2)", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + res := tc.db.InsertValueSQL(tc.names, tc.values, tc.isMulti, mi) + + assert.Equal(t, tc.wantRes, res) + }) + } +} + +func TestDbBase_UpdateSQL(t *testing.T) { + mi := &models.ModelInfo{ + Table: "test_table", + } + + testCases := []struct { + name string + db *dbBase + + setNames []string + pkName string + + wantRes string + }{ + { + name: "update by dbBase", + db: &dbBase{ + ins: &dbBase{}, + }, + setNames: []string{"name", "age", "sender"}, + pkName: "id", + wantRes: "UPDATE `test_table` SET `name` = ?, `age` = ?, `sender` = ? WHERE `id` = ?", + }, + { + name: "update by dbBasePostgres", + db: &dbBase{ + ins: newdbBasePostgres(), + }, + setNames: []string{"name", "age", "sender"}, + pkName: "id", + wantRes: "UPDATE \"test_table\" SET \"name\" = $1, \"age\" = $2, \"sender\" = $3 WHERE \"id\" = $4", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + res := tc.db.UpdateSQL(tc.setNames, tc.pkName, mi) + + assert.Equal(t, tc.wantRes, res) + }) + } +} + +func TestDbBase_DeleteSQL(t *testing.T) { + mi := &models.ModelInfo{ + Table: "test_table", + } + + testCases := []struct { + name string + db *dbBase + + whereCols []string + + wantRes string + }{ + { + name: "delete by dbBase with id", + db: &dbBase{ + ins: &dbBase{}, + }, + whereCols: []string{"id"}, + wantRes: "DELETE FROM `test_table` WHERE `id` = ?", + }, + { + name: "delete by dbBase not id", + db: &dbBase{ + ins: &dbBase{}, + }, + whereCols: []string{"name", "age"}, + wantRes: "DELETE FROM `test_table` WHERE `name` = ? AND `age` = ?", + }, + { + name: "delete by dbBasePostgres with id", + db: &dbBase{ + ins: newdbBasePostgres(), + }, + whereCols: []string{"id"}, + wantRes: "DELETE FROM \"test_table\" WHERE \"id\" = $1", + }, + { + name: "delete by dbBasePostgres not id", + db: &dbBase{ + ins: newdbBasePostgres(), + }, + whereCols: []string{"name", "age"}, + wantRes: "DELETE FROM \"test_table\" WHERE \"name\" = $1 AND \"age\" = $2", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + res := tc.db.DeleteSQL(tc.whereCols, mi) + + assert.Equal(t, tc.wantRes, res) + }) + } +} diff --git a/client/orm/db_tidb.go b/client/orm/db_tidb.go index 48c5b4e7..8d91b091 100644 --- a/client/orm/db_tidb.go +++ b/client/orm/db_tidb.go @@ -41,9 +41,9 @@ func (d *dbBaseTidb) ShowTablesQuery() string { return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema = DATABASE()" } -// show columns sql of table for mysql. +// show Columns sql of table for mysql. func (d *dbBaseTidb) ShowColumnsQuery(table string) string { - return fmt.Sprintf("SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE FROM information_schema.columns "+ + return fmt.Sprintf("SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE FROM information_schema.Columns "+ "WHERE table_schema = DATABASE() AND table_name = '%s'", table) } diff --git a/client/orm/db_utils.go b/client/orm/db_utils.go index 01f5a028..45c95f85 100644 --- a/client/orm/db_utils.go +++ b/client/orm/db_utils.go @@ -18,6 +18,10 @@ import ( "fmt" "reflect" "time" + + "github.com/beego/beego/v2/client/orm/internal/utils" + + "github.com/beego/beego/v2/client/orm/internal/models" ) // get table alias. @@ -29,32 +33,32 @@ func getDbAlias(name string) *alias { } // get pk column info. -func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interface{}, exist bool) { - fi := mi.fields.pk +func getExistPk(mi *models.ModelInfo, ind reflect.Value) (column string, value interface{}, exist bool) { + fi := mi.Fields.Pk - v := ind.FieldByIndex(fi.fieldIndex) - if fi.fieldType&IsPositiveIntegerField > 0 { + v := ind.FieldByIndex(fi.FieldIndex) + if fi.FieldType&IsPositiveIntegerField > 0 { vu := v.Uint() exist = vu > 0 value = vu - } else if fi.fieldType&IsIntegerField > 0 { + } else if fi.FieldType&IsIntegerField > 0 { vu := v.Int() exist = true value = vu - } else if fi.fieldType&IsRelField > 0 { - _, value, exist = getExistPk(fi.relModelInfo, reflect.Indirect(v)) + } else if fi.FieldType&IsRelField > 0 { + _, value, exist = getExistPk(fi.RelModelInfo, reflect.Indirect(v)) } else { vu := v.String() exist = vu != "" value = vu } - column = fi.column + column = fi.Column return } -// get fields description as flatted string. -func getFlatParams(fi *fieldInfo, args []interface{}, tz *time.Location) (params []interface{}) { +// get Fields description as flatted string. +func getFlatParams(fi *models.FieldInfo, args []interface{}, tz *time.Location) (params []interface{}) { outFor: for _, arg := range args { if arg == nil { @@ -74,32 +78,32 @@ outFor: case reflect.String: v := val.String() if fi != nil { - if fi.fieldType == TypeTimeField || fi.fieldType == TypeDateField || fi.fieldType == TypeDateTimeField { + if fi.FieldType == TypeTimeField || fi.FieldType == TypeDateField || fi.FieldType == TypeDateTimeField { var t time.Time var err error if len(v) >= 19 { s := v[:19] - t, err = time.ParseInLocation(formatDateTime, s, DefaultTimeLoc) + t, err = time.ParseInLocation(utils.FormatDateTime, s, DefaultTimeLoc) } else if len(v) >= 10 { s := v if len(v) > 10 { s = v[:10] } - t, err = time.ParseInLocation(formatDate, s, tz) + t, err = time.ParseInLocation(utils.FormatDate, s, tz) } else { s := v if len(s) > 8 { s = v[:8] } - t, err = time.ParseInLocation(formatTime, s, tz) + t, err = time.ParseInLocation(utils.FormatTime, s, tz) } if err == nil { - if fi.fieldType == TypeDateField { - v = t.In(tz).Format(formatDate) - } else if fi.fieldType == TypeDateTimeField { - v = t.In(tz).Format(formatDateTime) + if fi.FieldType == TypeDateField { + v = t.In(tz).Format(utils.FormatDate) + } else if fi.FieldType == TypeDateTimeField { + v = t.In(tz).Format(utils.FormatDateTime) } else { - v = t.In(tz).Format(formatTime) + v = t.In(tz).Format(utils.FormatTime) } } } @@ -110,7 +114,7 @@ outFor: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: arg = val.Uint() case reflect.Float32: - arg, _ = StrTo(ToStr(arg)).Float64() + arg, _ = utils.StrTo(utils.ToStr(arg)).Float64() case reflect.Float64: arg = val.Float() case reflect.Bool: @@ -143,18 +147,18 @@ outFor: continue outFor case reflect.Struct: if v, ok := arg.(time.Time); ok { - if fi != nil && fi.fieldType == TypeDateField { - arg = v.In(tz).Format(formatDate) - } else if fi != nil && fi.fieldType == TypeDateTimeField { - arg = v.In(tz).Format(formatDateTime) - } else if fi != nil && fi.fieldType == TypeTimeField { - arg = v.In(tz).Format(formatTime) + if fi != nil && fi.FieldType == TypeDateField { + arg = v.In(tz).Format(utils.FormatDate) + } else if fi != nil && fi.FieldType == TypeDateTimeField { + arg = v.In(tz).Format(utils.FormatDateTime) + } else if fi != nil && fi.FieldType == TypeTimeField { + arg = v.In(tz).Format(utils.FormatTime) } else { - arg = v.In(tz).Format(formatDateTime) + arg = v.In(tz).Format(utils.FormatDateTime) } } else { typ := val.Type() - name := getFullName(typ) + name := models.GetFullName(typ) var value interface{} if mmi, ok := defaultModelCache.getByFullName(name); ok { if _, vu, exist := getExistPk(mmi, val); exist { diff --git a/client/orm/filter.go b/client/orm/filter.go index bc13c3fa..cd313761 100644 --- a/client/orm/filter.go +++ b/client/orm/filter.go @@ -22,12 +22,12 @@ import ( // don't forget to call next(...) inside your Filter type FilterChain func(next Filter) Filter -// Filter's behavior is a little big strange. +// Filter behavior is a little big strange. // it's only be called when users call methods of Ormer // return value is an array. it's a little bit hard to understand, // for example, the Ormer's Read method only return error // so the filter processing this method should return an array whose first element is error -// and, Ormer's ReadOrCreateWithCtx return three values, so the Filter's result should contains three values +// and, Ormer's ReadOrCreateWithCtx return three values, so the Filter's result should contain three values type Filter func(ctx context.Context, inv *Invocation) []interface{} var globalFilterChains = make([]FilterChain, 0, 4) diff --git a/client/orm/filter_orm_decorator.go b/client/orm/filter_orm_decorator.go index 3b23284d..c8a28967 100644 --- a/client/orm/filter_orm_decorator.go +++ b/client/orm/filter_orm_decorator.go @@ -20,6 +20,10 @@ import ( "reflect" "time" + utils2 "github.com/beego/beego/v2/client/orm/internal/utils" + + "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/core/utils" ) @@ -192,13 +196,13 @@ func (f *filterOrmDecorator) QueryTable(ptrStructOrTableName interface{}) QueryS var ( name string md interface{} - mi *modelInfo + mi *models.ModelInfo ) if table, ok := ptrStructOrTableName.(string); ok { name = table } else { - name = getFullName(indirectType(reflect.TypeOf(ptrStructOrTableName))) + name = models.GetFullName(utils2.IndirectType(reflect.TypeOf(ptrStructOrTableName))) md = ptrStructOrTableName } @@ -303,7 +307,7 @@ func (f *filterOrmDecorator) InsertMulti(bulk int, mds interface{}) (int64, erro func (f *filterOrmDecorator) InsertMultiWithCtx(ctx context.Context, bulk int, mds interface{}) (int64, error) { var ( md interface{} - mi *modelInfo + mi *models.ModelInfo ) sind := reflect.Indirect(reflect.ValueOf(mds)) diff --git a/adapter/orm/orm_log.go b/client/orm/internal/buffers/buffers.go similarity index 63% rename from adapter/orm/orm_log.go rename to client/orm/internal/buffers/buffers.go index 1faab4ba..db341ff4 100644 --- a/adapter/orm/orm_log.go +++ b/client/orm/internal/buffers/buffers.go @@ -12,21 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -package orm +package buffers -import ( - "io" +import "github.com/valyala/bytebufferpool" - "github.com/beego/beego/v2/client/orm" -) +var _ Buffer = &bytebufferpool.ByteBuffer{} -// Log implement the log.Logger -type Log orm.Log - -// LogFunc is costomer log func -var LogFunc = orm.LogFunc - -// NewLog set io.Writer to create a Logger. -func NewLog(out io.Writer) *Log { - return (*Log)(orm.NewLog(out)) +type Buffer interface { + Write(p []byte) (int, error) + WriteString(s string) (int, error) + WriteByte(c byte) error + String() string +} + +func Get() Buffer { + return bytebufferpool.Get() +} + +func Put(bf Buffer) { + bytebufferpool.Put(bf.(*bytebufferpool.ByteBuffer)) } diff --git a/client/orm/internal/logs/log.go b/client/orm/internal/logs/log.go new file mode 100644 index 00000000..3ddde3ad --- /dev/null +++ b/client/orm/internal/logs/log.go @@ -0,0 +1,20 @@ +package logs + +import ( + "io" + "log" + "os" +) + +var DebugLog = NewLog(os.Stdout) + +// Log implement the log.Logger +type Log struct { + *log.Logger +} + +func NewLog(out io.Writer) *Log { + d := new(Log) + d.Logger = log.New(out, "[ORM]", log.LstdFlags) + return d +} diff --git a/adapter/orm/models_fields.go b/client/orm/internal/models/models_fields.go similarity index 65% rename from adapter/orm/models_fields.go rename to client/orm/internal/models/models_fields.go index ff0b0e87..70e5aafa 100644 --- a/adapter/orm/models_fields.go +++ b/client/orm/internal/models/models_fields.go @@ -12,81 +12,95 @@ // See the License for the specific language governing permissions and // limitations under the License. -package orm +package models import ( + "fmt" + "strconv" "time" - "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/client/orm/internal/utils" ) // Define the Type enum const ( - TypeBooleanField = orm.TypeBooleanField - TypeVarCharField = orm.TypeVarCharField - TypeCharField = orm.TypeCharField - TypeTextField = orm.TypeTextField - TypeTimeField = orm.TypeTimeField - TypeDateField = orm.TypeDateField - TypeDateTimeField = orm.TypeDateTimeField - TypeBitField = orm.TypeBitField - TypeSmallIntegerField = orm.TypeSmallIntegerField - TypeIntegerField = orm.TypeIntegerField - TypeBigIntegerField = orm.TypeBigIntegerField - TypePositiveBitField = orm.TypePositiveBitField - TypePositiveSmallIntegerField = orm.TypePositiveSmallIntegerField - TypePositiveIntegerField = orm.TypePositiveIntegerField - TypePositiveBigIntegerField = orm.TypePositiveBigIntegerField - TypeFloatField = orm.TypeFloatField - TypeDecimalField = orm.TypeDecimalField - TypeJSONField = orm.TypeJSONField - TypeJsonbField = orm.TypeJsonbField - RelForeignKey = orm.RelForeignKey - RelOneToOne = orm.RelOneToOne - RelManyToMany = orm.RelManyToMany - RelReverseOne = orm.RelReverseOne - RelReverseMany = orm.RelReverseMany + TypeBooleanField = 1 << iota + TypeVarCharField + TypeCharField + TypeTextField + TypeTimeField + TypeDateField + TypeDateTimeField + TypeBitField + TypeSmallIntegerField + TypeIntegerField + TypeBigIntegerField + TypePositiveBitField + TypePositiveSmallIntegerField + TypePositiveIntegerField + TypePositiveBigIntegerField + TypeFloatField + TypeDecimalField + TypeJSONField + TypeJsonbField + RelForeignKey + RelOneToOne + RelManyToMany + RelReverseOne + RelReverseMany ) // Define some logic enum const ( - IsIntegerField = orm.IsIntegerField - IsPositiveIntegerField = orm.IsPositiveIntegerField - IsRelField = orm.IsRelField - IsFieldType = orm.IsFieldType + IsIntegerField = ^-TypePositiveBigIntegerField >> 6 << 7 + IsPositiveIntegerField = ^-TypePositiveBigIntegerField >> 10 << 11 + IsRelField = ^-RelReverseMany >> 18 << 19 + IsFieldType = ^-RelReverseMany<<1 + 1 ) // BooleanField A true/false field. -type BooleanField orm.BooleanField +type BooleanField bool // Value return the BooleanField func (e BooleanField) Value() bool { - return orm.BooleanField(e).Value() + return bool(e) } // Set will set the BooleanField func (e *BooleanField) Set(d bool) { - (*orm.BooleanField)(e).Set(d) + *e = BooleanField(d) } // String format the Bool to string func (e *BooleanField) String() string { - return (*orm.BooleanField)(e).String() + return strconv.FormatBool(e.Value()) } // FieldType return BooleanField the type func (e *BooleanField) FieldType() int { - return (*orm.BooleanField)(e).FieldType() + return TypeBooleanField } // SetRaw set the interface to bool func (e *BooleanField) SetRaw(value interface{}) error { - return (*orm.BooleanField)(e).SetRaw(value) + switch d := value.(type) { + case bool: + e.Set(d) + case string: + v, err := utils.StrTo(d).Bool() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return the current value func (e *BooleanField) RawValue() interface{} { - return (*orm.BooleanField)(e).RawValue() + return e.Value() } // verify the BooleanField implement the Fielder interface @@ -96,36 +110,42 @@ var _ Fielder = new(BooleanField) // required values tag: size // The size is enforced at the database level and in models’s validation. // eg: `orm:"size(120)"` -type CharField orm.CharField +type CharField string // Value return the CharField's Value func (e CharField) Value() string { - return orm.CharField(e).Value() + return string(e) } // Set CharField value func (e *CharField) Set(d string) { - (*orm.CharField)(e).Set(d) + *e = CharField(d) } // String return the CharField func (e *CharField) String() string { - return (*orm.CharField)(e).String() + return e.Value() } // FieldType return the enum type func (e *CharField) FieldType() int { - return (*orm.CharField)(e).FieldType() + return TypeVarCharField } // SetRaw set the interface to string func (e *CharField) SetRaw(value interface{}) error { - return (*orm.CharField)(e).SetRaw(value) + switch d := value.(type) { + case string: + e.Set(d) + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return the CharField value func (e *CharField) RawValue() interface{} { - return (*orm.CharField)(e).RawValue() + return e.Value() } // verify CharField implement Fielder @@ -144,36 +164,48 @@ var _ Fielder = new(CharField) // Note that the current date is always used; it’s not just a default value that you can override. // // eg: `orm:"auto_now"` or `orm:"auto_now_add"` -type TimeField orm.TimeField +type TimeField time.Time // Value return the time.Time func (e TimeField) Value() time.Time { - return orm.TimeField(e).Value() + return time.Time(e) } // Set set the TimeField's value func (e *TimeField) Set(d time.Time) { - (*orm.TimeField)(e).Set(d) + *e = TimeField(d) } // String convert time to string func (e *TimeField) String() string { - return (*orm.TimeField)(e).String() + return e.Value().String() } // FieldType return enum type Date func (e *TimeField) FieldType() int { - return (*orm.TimeField)(e).FieldType() + return TypeDateField } // SetRaw convert the interface to time.Time. Allow string and time.Time func (e *TimeField) SetRaw(value interface{}) error { - return (*orm.TimeField)(e).SetRaw(value) + switch d := value.(type) { + case time.Time: + e.Set(d) + case string: + v, err := utils.TimeParse(d, utils.FormatTime) + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return time value func (e *TimeField) RawValue() interface{} { - return (*orm.TimeField)(e).RawValue() + return e.Value() } var _ Fielder = new(TimeField) @@ -191,36 +223,48 @@ var _ Fielder = new(TimeField) // Note that the current date is always used; it’s not just a default value that you can override. // // eg: `orm:"auto_now"` or `orm:"auto_now_add"` -type DateField orm.DateField +type DateField time.Time // Value return the time.Time func (e DateField) Value() time.Time { - return orm.DateField(e).Value() + return time.Time(e) } // Set set the DateField's value func (e *DateField) Set(d time.Time) { - (*orm.DateField)(e).Set(d) + *e = DateField(d) } // String convert datetime to string func (e *DateField) String() string { - return (*orm.DateField)(e).String() + return e.Value().String() } // FieldType return enum type Date func (e *DateField) FieldType() int { - return (*orm.DateField)(e).FieldType() + return TypeDateField } // SetRaw convert the interface to time.Time. Allow string and time.Time func (e *DateField) SetRaw(value interface{}) error { - return (*orm.DateField)(e).SetRaw(value) + switch d := value.(type) { + case time.Time: + e.Set(d) + case string: + v, err := utils.TimeParse(d, utils.FormatDate) + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return Date value func (e *DateField) RawValue() interface{} { - return (*orm.DateField)(e).RawValue() + return e.Value() } // verify DateField implement fielder interface @@ -229,396 +273,512 @@ var _ Fielder = new(DateField) // DateTimeField A date, represented in go by a time.Time instance. // datetime values like 2006-01-02 15:04:05 // Takes the same extra arguments as DateField. -type DateTimeField orm.DateTimeField +type DateTimeField time.Time // Value return the datetime value func (e DateTimeField) Value() time.Time { - return orm.DateTimeField(e).Value() + return time.Time(e) } // Set set the time.Time to datetime func (e *DateTimeField) Set(d time.Time) { - (*orm.DateTimeField)(e).Set(d) + *e = DateTimeField(d) } // String return the time's String func (e *DateTimeField) String() string { - return (*orm.DateTimeField)(e).String() + return e.Value().String() } // FieldType return the enum TypeDateTimeField func (e *DateTimeField) FieldType() int { - return (*orm.DateTimeField)(e).FieldType() + return TypeDateTimeField } // SetRaw convert the string or time.Time to DateTimeField func (e *DateTimeField) SetRaw(value interface{}) error { - return (*orm.DateTimeField)(e).SetRaw(value) + switch d := value.(type) { + case time.Time: + e.Set(d) + case string: + v, err := utils.TimeParse(d, utils.FormatDateTime) + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return the datetime value func (e *DateTimeField) RawValue() interface{} { - return (*orm.DateTimeField)(e).RawValue() + return e.Value() } // verify datetime implement fielder var _ Fielder = new(DateTimeField) // FloatField A floating-point number represented in go by a float32 value. -type FloatField orm.FloatField +type FloatField float64 // Value return the FloatField value func (e FloatField) Value() float64 { - return orm.FloatField(e).Value() + return float64(e) } // Set the Float64 func (e *FloatField) Set(d float64) { - (*orm.FloatField)(e).Set(d) + *e = FloatField(d) } // String return the string func (e *FloatField) String() string { - return (*orm.FloatField)(e).String() + return utils.ToStr(e.Value(), -1, 32) } // FieldType return the enum type func (e *FloatField) FieldType() int { - return (*orm.FloatField)(e).FieldType() + return TypeFloatField } // SetRaw converter interface Float64 float32 or string to FloatField func (e *FloatField) SetRaw(value interface{}) error { - return (*orm.FloatField)(e).SetRaw(value) + switch d := value.(type) { + case float32: + e.Set(float64(d)) + case float64: + e.Set(d) + case string: + v, err := utils.StrTo(d).Float64() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return the FloatField value func (e *FloatField) RawValue() interface{} { - return (*orm.FloatField)(e).RawValue() + return e.Value() } // verify FloatField implement Fielder var _ Fielder = new(FloatField) // SmallIntegerField -32768 to 32767 -type SmallIntegerField orm.SmallIntegerField +type SmallIntegerField int16 // Value return int16 value func (e SmallIntegerField) Value() int16 { - return orm.SmallIntegerField(e).Value() + return int16(e) } // Set the SmallIntegerField value func (e *SmallIntegerField) Set(d int16) { - (*orm.SmallIntegerField)(e).Set(d) + *e = SmallIntegerField(d) } // String convert smallint to string func (e *SmallIntegerField) String() string { - return (*orm.SmallIntegerField)(e).String() + return utils.ToStr(e.Value()) } // FieldType return enum type SmallIntegerField func (e *SmallIntegerField) FieldType() int { - return (*orm.SmallIntegerField)(e).FieldType() + return TypeSmallIntegerField } // SetRaw convert interface int16/string to int16 func (e *SmallIntegerField) SetRaw(value interface{}) error { - return (*orm.SmallIntegerField)(e).SetRaw(value) + switch d := value.(type) { + case int16: + e.Set(d) + case string: + v, err := utils.StrTo(d).Int16() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return smallint value func (e *SmallIntegerField) RawValue() interface{} { - return (*orm.SmallIntegerField)(e).RawValue() + return e.Value() } // verify SmallIntegerField implement Fielder var _ Fielder = new(SmallIntegerField) // IntegerField -2147483648 to 2147483647 -type IntegerField orm.IntegerField +type IntegerField int32 // Value return the int32 func (e IntegerField) Value() int32 { - return orm.IntegerField(e).Value() + return int32(e) } // Set IntegerField value func (e *IntegerField) Set(d int32) { - (*orm.IntegerField)(e).Set(d) + *e = IntegerField(d) } // String convert Int32 to string func (e *IntegerField) String() string { - return (*orm.IntegerField)(e).String() + return utils.ToStr(e.Value()) } // FieldType return the enum type func (e *IntegerField) FieldType() int { - return (*orm.IntegerField)(e).FieldType() + return TypeIntegerField } // SetRaw convert interface int32/string to int32 func (e *IntegerField) SetRaw(value interface{}) error { - return (*orm.IntegerField)(e).SetRaw(value) + switch d := value.(type) { + case int32: + e.Set(d) + case string: + v, err := utils.StrTo(d).Int32() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return IntegerField value func (e *IntegerField) RawValue() interface{} { - return (*orm.IntegerField)(e).RawValue() + return e.Value() } // verify IntegerField implement Fielder var _ Fielder = new(IntegerField) // BigIntegerField -9223372036854775808 to 9223372036854775807. -type BigIntegerField orm.BigIntegerField +type BigIntegerField int64 // Value return int64 func (e BigIntegerField) Value() int64 { - return orm.BigIntegerField(e).Value() + return int64(e) } // Set the BigIntegerField value func (e *BigIntegerField) Set(d int64) { - (*orm.BigIntegerField)(e).Set(d) + *e = BigIntegerField(d) } // String convert BigIntegerField to string func (e *BigIntegerField) String() string { - return (*orm.BigIntegerField)(e).String() + return utils.ToStr(e.Value()) } // FieldType return enum type func (e *BigIntegerField) FieldType() int { - return (*orm.BigIntegerField)(e).FieldType() + return TypeBigIntegerField } // SetRaw convert interface int64/string to int64 func (e *BigIntegerField) SetRaw(value interface{}) error { - return (*orm.BigIntegerField)(e).SetRaw(value) + switch d := value.(type) { + case int64: + e.Set(d) + case string: + v, err := utils.StrTo(d).Int64() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return BigIntegerField value func (e *BigIntegerField) RawValue() interface{} { - return (*orm.BigIntegerField)(e).RawValue() + return e.Value() } // verify BigIntegerField implement Fielder var _ Fielder = new(BigIntegerField) // PositiveSmallIntegerField 0 to 65535 -type PositiveSmallIntegerField orm.PositiveSmallIntegerField +type PositiveSmallIntegerField uint16 // Value return uint16 func (e PositiveSmallIntegerField) Value() uint16 { - return orm.PositiveSmallIntegerField(e).Value() + return uint16(e) } // Set PositiveSmallIntegerField value func (e *PositiveSmallIntegerField) Set(d uint16) { - (*orm.PositiveSmallIntegerField)(e).Set(d) + *e = PositiveSmallIntegerField(d) } // String convert uint16 to string func (e *PositiveSmallIntegerField) String() string { - return (*orm.PositiveSmallIntegerField)(e).String() + return utils.ToStr(e.Value()) } // FieldType return enum type func (e *PositiveSmallIntegerField) FieldType() int { - return (*orm.PositiveSmallIntegerField)(e).FieldType() + return TypePositiveSmallIntegerField } // SetRaw convert Interface uint16/string to uint16 func (e *PositiveSmallIntegerField) SetRaw(value interface{}) error { - return (*orm.PositiveSmallIntegerField)(e).SetRaw(value) + switch d := value.(type) { + case uint16: + e.Set(d) + case string: + v, err := utils.StrTo(d).Uint16() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue returns PositiveSmallIntegerField value func (e *PositiveSmallIntegerField) RawValue() interface{} { - return (*orm.PositiveSmallIntegerField)(e).RawValue() + return e.Value() } // verify PositiveSmallIntegerField implement Fielder var _ Fielder = new(PositiveSmallIntegerField) // PositiveIntegerField 0 to 4294967295 -type PositiveIntegerField orm.PositiveIntegerField +type PositiveIntegerField uint32 // Value return PositiveIntegerField value. Uint32 func (e PositiveIntegerField) Value() uint32 { - return orm.PositiveIntegerField(e).Value() + return uint32(e) } // Set the PositiveIntegerField value func (e *PositiveIntegerField) Set(d uint32) { - (*orm.PositiveIntegerField)(e).Set(d) + *e = PositiveIntegerField(d) } // String convert PositiveIntegerField to string func (e *PositiveIntegerField) String() string { - return (*orm.PositiveIntegerField)(e).String() + return utils.ToStr(e.Value()) } // FieldType return enum type func (e *PositiveIntegerField) FieldType() int { - return (*orm.PositiveIntegerField)(e).FieldType() + return TypePositiveIntegerField } // SetRaw convert interface uint32/string to Uint32 func (e *PositiveIntegerField) SetRaw(value interface{}) error { - return (*orm.PositiveIntegerField)(e).SetRaw(value) + switch d := value.(type) { + case uint32: + e.Set(d) + case string: + v, err := utils.StrTo(d).Uint32() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return the PositiveIntegerField Value func (e *PositiveIntegerField) RawValue() interface{} { - return (*orm.PositiveIntegerField)(e).RawValue() + return e.Value() } // verify PositiveIntegerField implement Fielder var _ Fielder = new(PositiveIntegerField) // PositiveBigIntegerField 0 to 18446744073709551615 -type PositiveBigIntegerField orm.PositiveBigIntegerField +type PositiveBigIntegerField uint64 // Value return uint64 func (e PositiveBigIntegerField) Value() uint64 { - return orm.PositiveBigIntegerField(e).Value() + return uint64(e) } // Set PositiveBigIntegerField value func (e *PositiveBigIntegerField) Set(d uint64) { - (*orm.PositiveBigIntegerField)(e).Set(d) + *e = PositiveBigIntegerField(d) } // String convert PositiveBigIntegerField to string func (e *PositiveBigIntegerField) String() string { - return (*orm.PositiveBigIntegerField)(e).String() + return utils.ToStr(e.Value()) } // FieldType return enum type func (e *PositiveBigIntegerField) FieldType() int { - return (*orm.PositiveBigIntegerField)(e).FieldType() + return TypePositiveIntegerField } // SetRaw convert interface uint64/string to Uint64 func (e *PositiveBigIntegerField) SetRaw(value interface{}) error { - return (*orm.PositiveBigIntegerField)(e).SetRaw(value) + switch d := value.(type) { + case uint64: + e.Set(d) + case string: + v, err := utils.StrTo(d).Uint64() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return PositiveBigIntegerField value func (e *PositiveBigIntegerField) RawValue() interface{} { - return (*orm.PositiveBigIntegerField)(e).RawValue() + return e.Value() } // verify PositiveBigIntegerField implement Fielder var _ Fielder = new(PositiveBigIntegerField) // TextField A large text field. -type TextField orm.TextField +type TextField string // Value return TextField value func (e TextField) Value() string { - return orm.TextField(e).Value() + return string(e) } // Set the TextField value func (e *TextField) Set(d string) { - (*orm.TextField)(e).Set(d) + *e = TextField(d) } // String convert TextField to string func (e *TextField) String() string { - return (*orm.TextField)(e).String() + return e.Value() } // FieldType return enum type func (e *TextField) FieldType() int { - return (*orm.TextField)(e).FieldType() + return TypeTextField } // SetRaw convert interface string to string func (e *TextField) SetRaw(value interface{}) error { - return (*orm.TextField)(e).SetRaw(value) + switch d := value.(type) { + case string: + e.Set(d) + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return TextField value func (e *TextField) RawValue() interface{} { - return (*orm.TextField)(e).RawValue() + return e.Value() } // verify TextField implement Fielder var _ Fielder = new(TextField) // JSONField postgres json field. -type JSONField orm.JSONField +type JSONField string // Value return JSONField value func (j JSONField) Value() string { - return orm.JSONField(j).Value() + return string(j) } // Set the JSONField value func (j *JSONField) Set(d string) { - (*orm.JSONField)(j).Set(d) + *j = JSONField(d) } // String convert JSONField to string func (j *JSONField) String() string { - return (*orm.JSONField)(j).String() + return j.Value() } // FieldType return enum type func (j *JSONField) FieldType() int { - return (*orm.JSONField)(j).FieldType() + return TypeJSONField } // SetRaw convert interface string to string func (j *JSONField) SetRaw(value interface{}) error { - return (*orm.JSONField)(j).SetRaw(value) + switch d := value.(type) { + case string: + j.Set(d) + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return JSONField value func (j *JSONField) RawValue() interface{} { - return (*orm.JSONField)(j).RawValue() + return j.Value() } // verify JSONField implement Fielder var _ Fielder = new(JSONField) // JsonbField postgres json field. -type JsonbField orm.JsonbField +type JsonbField string // Value return JsonbField value func (j JsonbField) Value() string { - return orm.JsonbField(j).Value() + return string(j) } // Set the JsonbField value func (j *JsonbField) Set(d string) { - (*orm.JsonbField)(j).Set(d) + *j = JsonbField(d) } // String convert JsonbField to string func (j *JsonbField) String() string { - return (*orm.JsonbField)(j).String() + return j.Value() } // FieldType return enum type func (j *JsonbField) FieldType() int { - return (*orm.JsonbField)(j).FieldType() + return TypeJsonbField } // SetRaw convert interface string to string func (j *JsonbField) SetRaw(value interface{}) error { - return (*orm.JsonbField)(j).SetRaw(value) + switch d := value.(type) { + case string: + j.Set(d) + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil } // RawValue return JsonbField value func (j *JsonbField) RawValue() interface{} { - return (*orm.JsonbField)(j).RawValue() + return j.Value() } // verify JsonbField implement Fielder diff --git a/client/orm/models_info_f.go b/client/orm/internal/models/models_info_f.go similarity index 60% rename from client/orm/models_info_f.go rename to client/orm/internal/models/models_info_f.go index 6a9e7a99..3e5e4d6b 100644 --- a/client/orm/models_info_f.go +++ b/client/orm/internal/models/models_info_f.go @@ -12,147 +12,149 @@ // See the License for the specific language governing permissions and // limitations under the License. -package orm +package models import ( "errors" "fmt" "reflect" "strings" + + "github.com/beego/beego/v2/client/orm/internal/utils" ) var errSkipField = errors.New("skip field") -// field info collection -type fields struct { - pk *fieldInfo - columns map[string]*fieldInfo - fields map[string]*fieldInfo - fieldsLow map[string]*fieldInfo - fieldsByType map[int][]*fieldInfo - fieldsRel []*fieldInfo - fieldsReverse []*fieldInfo - fieldsDB []*fieldInfo - rels []*fieldInfo - orders []string - dbcols []string +// Fields field info collection +type Fields struct { + Pk *FieldInfo + Columns map[string]*FieldInfo + Fields map[string]*FieldInfo + FieldsLow map[string]*FieldInfo + FieldsByType map[int][]*FieldInfo + FieldsRel []*FieldInfo + FieldsReverse []*FieldInfo + FieldsDB []*FieldInfo + Rels []*FieldInfo + Orders []string + DBcols []string } -// add field info -func (f *fields) Add(fi *fieldInfo) (added bool) { - if f.fields[fi.name] == nil && f.columns[fi.column] == nil { - f.columns[fi.column] = fi - f.fields[fi.name] = fi - f.fieldsLow[strings.ToLower(fi.name)] = fi +// Add adds field info +func (f *Fields) Add(fi *FieldInfo) (added bool) { + if f.Fields[fi.Name] == nil && f.Columns[fi.Column] == nil { + f.Columns[fi.Column] = fi + f.Fields[fi.Name] = fi + f.FieldsLow[strings.ToLower(fi.Name)] = fi } else { return } - if _, ok := f.fieldsByType[fi.fieldType]; !ok { - f.fieldsByType[fi.fieldType] = make([]*fieldInfo, 0) + if _, ok := f.FieldsByType[fi.FieldType]; !ok { + f.FieldsByType[fi.FieldType] = make([]*FieldInfo, 0) } - f.fieldsByType[fi.fieldType] = append(f.fieldsByType[fi.fieldType], fi) - f.orders = append(f.orders, fi.column) - if fi.dbcol { - f.dbcols = append(f.dbcols, fi.column) - f.fieldsDB = append(f.fieldsDB, fi) + f.FieldsByType[fi.FieldType] = append(f.FieldsByType[fi.FieldType], fi) + f.Orders = append(f.Orders, fi.Column) + if fi.DBcol { + f.DBcols = append(f.DBcols, fi.Column) + f.FieldsDB = append(f.FieldsDB, fi) } - if fi.rel { - f.fieldsRel = append(f.fieldsRel, fi) + if fi.Rel { + f.FieldsRel = append(f.FieldsRel, fi) } - if fi.reverse { - f.fieldsReverse = append(f.fieldsReverse, fi) + if fi.Reverse { + f.FieldsReverse = append(f.FieldsReverse, fi) } return true } -// get field info by name -func (f *fields) GetByName(name string) *fieldInfo { - return f.fields[name] +// GetByName get field info by name +func (f *Fields) GetByName(name string) *FieldInfo { + return f.Fields[name] } -// get field info by column name -func (f *fields) GetByColumn(column string) *fieldInfo { - return f.columns[column] +// GetByColumn get field info by column name +func (f *Fields) GetByColumn(column string) *FieldInfo { + return f.Columns[column] } -// get field info by string, name is prior -func (f *fields) GetByAny(name string) (*fieldInfo, bool) { - if fi, ok := f.fields[name]; ok { +// GetByAny get field info by string, name is prior +func (f *Fields) GetByAny(name string) (*FieldInfo, bool) { + if fi, ok := f.Fields[name]; ok { return fi, ok } - if fi, ok := f.fieldsLow[strings.ToLower(name)]; ok { + if fi, ok := f.FieldsLow[strings.ToLower(name)]; ok { return fi, ok } - if fi, ok := f.columns[name]; ok { + if fi, ok := f.Columns[name]; ok { return fi, ok } return nil, false } -// create new field info collection -func newFields() *fields { - f := new(fields) - f.fields = make(map[string]*fieldInfo) - f.fieldsLow = make(map[string]*fieldInfo) - f.columns = make(map[string]*fieldInfo) - f.fieldsByType = make(map[int][]*fieldInfo) +// NewFields create new field info collection +func NewFields() *Fields { + f := new(Fields) + f.Fields = make(map[string]*FieldInfo) + f.FieldsLow = make(map[string]*FieldInfo) + f.Columns = make(map[string]*FieldInfo) + f.FieldsByType = make(map[int][]*FieldInfo) return f } -// single field info -type fieldInfo struct { - dbcol bool // table column fk and onetoone - inModel bool - auto bool - pk bool - null bool - index bool - unique bool - colDefault bool // whether has default tag - toText bool - autoNow bool - autoNowAdd bool - rel bool // if type equal to RelForeignKey, RelOneToOne, RelManyToMany then true - reverse bool - isFielder bool // implement Fielder interface - mi *modelInfo - fieldIndex []int - fieldType int - name string - fullName string - column string - addrValue reflect.Value - sf reflect.StructField - initial StrTo // store the default value - size int - reverseField string - reverseFieldInfo *fieldInfo - reverseFieldInfoTwo *fieldInfo - reverseFieldInfoM2M *fieldInfo - relTable string - relThrough string - relThroughModelInfo *modelInfo - relModelInfo *modelInfo - digits int - decimals int - onDelete string - description string - timePrecision *int +// FieldInfo single field info +type FieldInfo struct { + DBcol bool // table column fk and onetoone + InModel bool + Auto bool + Pk bool + Null bool + Index bool + Unique bool + ColDefault bool // whether has default tag + ToText bool + AutoNow bool + AutoNowAdd bool + Rel bool // if type equal to RelForeignKey, RelOneToOne, RelManyToMany then true + Reverse bool + IsFielder bool // implement Fielder interface + Mi *ModelInfo + FieldIndex []int + FieldType int + Name string + FullName string + Column string + AddrValue reflect.Value + Sf reflect.StructField + Initial utils.StrTo // store the default value + Size int + ReverseField string + ReverseFieldInfo *FieldInfo + ReverseFieldInfoTwo *FieldInfo + ReverseFieldInfoM2M *FieldInfo + RelTable string + RelThrough string + RelThroughModelInfo *ModelInfo + RelModelInfo *ModelInfo + Digits int + Decimals int + OnDelete string + Description string + TimePrecision *int } -// new field info -func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField, mName string) (fi *fieldInfo, err error) { +// NewFieldInfo new field info +func NewFieldInfo(mi *ModelInfo, field reflect.Value, sf reflect.StructField, mName string) (fi *FieldInfo, err error) { var ( tag string tagValue string - initial StrTo // store the default value + initial utils.StrTo // store the default value fieldType int attrs map[string]bool tags map[string]string addrField reflect.Value ) - fi = new(fieldInfo) + fi = new(FieldInfo) // if field which CanAddr is the follow type // A value is addressable if it is an element of a slice, @@ -168,7 +170,7 @@ func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField, mN } } - attrs, tags = parseStructTag(sf.Tag.Get(defaultStructTagName)) + attrs, tags = ParseStructTag(sf.Tag.Get(DefaultStructTagName)) if _, ok := attrs["-"]; ok { return nil, errSkipField @@ -187,7 +189,7 @@ func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField, mN checkType: switch f := addrField.Interface().(type) { case Fielder: - fi.isFielder = true + fi.IsFielder = true if field.Kind() == reflect.Ptr { err = fmt.Errorf("the model Fielder can not be use ptr") goto end @@ -211,9 +213,9 @@ checkType: case "m2m": fieldType = RelManyToMany if tv := tags["rel_table"]; tv != "" { - fi.relTable = tv + fi.RelTable = tv } else if tv := tags["rel_through"]; tv != "" { - fi.relThrough = tv + fi.RelThrough = tv } break checkType default: @@ -231,9 +233,9 @@ checkType: case "many": fieldType = RelReverseMany if tv := tags["rel_table"]; tv != "" { - fi.relTable = tv + fi.RelTable = tv } else if tv := tags["rel_through"]; tv != "" { - fi.relThrough = tv + fi.RelThrough = tv } break checkType default: @@ -295,117 +297,117 @@ checkType: goto end } - fi.fieldType = fieldType - fi.name = sf.Name - fi.column = getColumnName(fieldType, addrField, sf, tags["column"]) - fi.addrValue = addrField - fi.sf = sf - fi.fullName = mi.fullName + mName + "." + sf.Name + fi.FieldType = fieldType + fi.Name = sf.Name + fi.Column = getColumnName(fieldType, addrField, sf, tags["column"]) + fi.AddrValue = addrField + fi.Sf = sf + fi.FullName = mi.FullName + mName + "." + sf.Name - fi.description = tags["description"] - fi.null = attrs["null"] - fi.index = attrs["index"] - fi.auto = attrs["auto"] - fi.pk = attrs["pk"] - fi.unique = attrs["unique"] + fi.Description = tags["description"] + fi.Null = attrs["null"] + fi.Index = attrs["index"] + fi.Auto = attrs["auto"] + fi.Pk = attrs["pk"] + fi.Unique = attrs["unique"] // Mark object property if there is attribute "default" in the orm configuration if _, ok := tags["default"]; ok { - fi.colDefault = true + fi.ColDefault = true } switch fieldType { case RelManyToMany, RelReverseMany, RelReverseOne: - fi.null = false - fi.index = false - fi.auto = false - fi.pk = false - fi.unique = false + fi.Null = false + fi.Index = false + fi.Auto = false + fi.Pk = false + fi.Unique = false default: - fi.dbcol = true + fi.DBcol = true } switch fieldType { case RelForeignKey, RelOneToOne, RelManyToMany: - fi.rel = true + fi.Rel = true if fieldType == RelOneToOne { - fi.unique = true + fi.Unique = true } case RelReverseMany, RelReverseOne: - fi.reverse = true + fi.Reverse = true } - if fi.rel && fi.dbcol { + if fi.Rel && fi.DBcol { switch onDelete { - case odCascade, odDoNothing: - case odSetDefault: + case OdCascade, OdDoNothing: + case OdSetDefault: if !initial.Exist() { err = errors.New("on_delete: set_default need set field a default value") goto end } - case odSetNULL: - if !fi.null { + case OdSetNULL: + if !fi.Null { err = errors.New("on_delete: set_null need set field null") goto end } default: if onDelete == "" { - onDelete = odCascade + onDelete = OdCascade } else { err = fmt.Errorf("on_delete value expected choice in `cascade,set_null,set_default,do_nothing`, unknown `%s`", onDelete) goto end } } - fi.onDelete = onDelete + fi.OnDelete = onDelete } switch fieldType { case TypeBooleanField: case TypeVarCharField, TypeCharField, TypeJSONField, TypeJsonbField: if size != "" { - v, e := StrTo(size).Int32() + v, e := utils.StrTo(size).Int32() if e != nil { err = fmt.Errorf("wrong size value `%s`", size) } else { - fi.size = int(v) + fi.Size = int(v) } } else { - fi.size = 255 - fi.toText = true + fi.Size = 255 + fi.ToText = true } case TypeTextField: - fi.index = false - fi.unique = false + fi.Index = false + fi.Unique = false case TypeTimeField, TypeDateField, TypeDateTimeField: if fieldType == TypeDateTimeField { if precision != "" { - v, e := StrTo(precision).Int() + v, e := utils.StrTo(precision).Int() if e != nil { err = fmt.Errorf("convert %s to int error:%v", precision, e) } else { - fi.timePrecision = &v + fi.TimePrecision = &v } } } if attrs["auto_now"] { - fi.autoNow = true + fi.AutoNow = true } else if attrs["auto_now_add"] { - fi.autoNowAdd = true + fi.AutoNowAdd = true } case TypeFloatField: case TypeDecimalField: d1 := digits d2 := decimals - v1, er1 := StrTo(d1).Int8() - v2, er2 := StrTo(d2).Int8() + v1, er1 := utils.StrTo(d1).Int8() + v2, er2 := utils.StrTo(d2).Int8() if er1 != nil || er2 != nil { err = fmt.Errorf("wrong digits/decimals value %s/%s", d2, d1) goto end } - fi.digits = int(v1) - fi.decimals = int(v2) + fi.Digits = int(v1) + fi.Decimals = int(v2) default: switch { case fieldType&IsIntegerField > 0: @@ -414,33 +416,33 @@ checkType: } if fieldType&IsIntegerField == 0 { - if fi.auto { + if fi.Auto { err = fmt.Errorf("non-integer type cannot set auto") goto end } } - if fi.auto || fi.pk { - if fi.auto { + if fi.Auto || fi.Pk { + if fi.Auto { switch addrField.Elem().Kind() { case reflect.Int, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint32, reflect.Uint64: default: err = fmt.Errorf("auto primary key only support int, int32, int64, uint, uint32, uint64 but found `%s`", addrField.Elem().Kind()) goto end } - fi.pk = true + fi.Pk = true } - fi.null = false - fi.index = false - fi.unique = false + fi.Null = false + fi.Index = false + fi.Unique = false } - if fi.unique { - fi.index = false + if fi.Unique { + fi.Index = false } // can not set default for these type - if fi.auto || fi.pk || fi.unique || fieldType == TypeTimeField || fieldType == TypeDateField || fieldType == TypeDateTimeField { + if fi.Auto || fi.Pk || fi.Unique || fieldType == TypeTimeField || fieldType == TypeDateField || fieldType == TypeDateTimeField { initial.Clear() } @@ -474,7 +476,7 @@ checkType: } } - fi.initial = initial + fi.Initial = initial end: if err != nil { return nil, err diff --git a/client/orm/internal/models/models_info_m.go b/client/orm/internal/models/models_info_m.go new file mode 100644 index 00000000..0dee0aa8 --- /dev/null +++ b/client/orm/internal/models/models_info_m.go @@ -0,0 +1,148 @@ +// Copyright 2014 beego Author. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package models + +import ( + "fmt" + "os" + "reflect" +) + +// ModelInfo single model info +type ModelInfo struct { + Manual bool + IsThrough bool + Pkg string + Name string + FullName string + Table string + Model interface{} + Fields *Fields + AddrField reflect.Value // store the original struct value + Uniques []string +} + +// NewModelInfo new model info +func NewModelInfo(val reflect.Value) (mi *ModelInfo) { + mi = &ModelInfo{} + mi.Fields = NewFields() + ind := reflect.Indirect(val) + mi.AddrField = val + mi.Name = ind.Type().Name() + mi.FullName = GetFullName(ind.Type()) + AddModelFields(mi, ind, "", []int{}) + return +} + +// AddModelFields index: FieldByIndex returns the nested field corresponding to index +func AddModelFields(mi *ModelInfo, ind reflect.Value, mName string, index []int) { + var ( + err error + fi *FieldInfo + sf reflect.StructField + ) + + for i := 0; i < ind.NumField(); i++ { + field := ind.Field(i) + sf = ind.Type().Field(i) + // if the field is unexported skip + if sf.PkgPath != "" { + continue + } + // add anonymous struct Fields + if sf.Anonymous { + AddModelFields(mi, field, mName+"."+sf.Name, append(index, i)) + continue + } + + fi, err = NewFieldInfo(mi, field, sf, mName) + if err == errSkipField { + err = nil + continue + } else if err != nil { + break + } + // record current field index + fi.FieldIndex = append(fi.FieldIndex, index...) + fi.FieldIndex = append(fi.FieldIndex, i) + fi.Mi = mi + fi.InModel = true + if !mi.Fields.Add(fi) { + err = fmt.Errorf("duplicate column name: %s", fi.Column) + break + } + if fi.Pk { + if mi.Fields.Pk != nil { + err = fmt.Errorf("one model must have one pk field only") + break + } else { + mi.Fields.Pk = fi + } + } + } + + if err != nil { + fmt.Println(fmt.Errorf("field: %s.%s, %s", ind.Type(), sf.Name, err)) + os.Exit(2) + } +} + +// NewM2MModelInfo combine related model info to new model info. +// prepare for relation models query. +func NewM2MModelInfo(m1, m2 *ModelInfo) (mi *ModelInfo) { + mi = new(ModelInfo) + mi.Fields = NewFields() + mi.Table = m1.Table + "_" + m2.Table + "s" + mi.Name = CamelString(mi.Table) + mi.FullName = m1.Pkg + "." + mi.Name + + fa := new(FieldInfo) // pk + f1 := new(FieldInfo) // m1 table RelForeignKey + f2 := new(FieldInfo) // m2 table RelForeignKey + fa.FieldType = TypeBigIntegerField + fa.Auto = true + fa.Pk = true + fa.DBcol = true + fa.Name = "Id" + fa.Column = "id" + fa.FullName = mi.FullName + "." + fa.Name + + f1.DBcol = true + f2.DBcol = true + f1.FieldType = RelForeignKey + f2.FieldType = RelForeignKey + f1.Name = CamelString(m1.Table) + f2.Name = CamelString(m2.Table) + f1.FullName = mi.FullName + "." + f1.Name + f2.FullName = mi.FullName + "." + f2.Name + f1.Column = m1.Table + "_id" + f2.Column = m2.Table + "_id" + f1.Rel = true + f2.Rel = true + f1.RelTable = m1.Table + f2.RelTable = m2.Table + f1.RelModelInfo = m1 + f2.RelModelInfo = m2 + f1.Mi = mi + f2.Mi = mi + + mi.Fields.Add(fa) + mi.Fields.Add(f1) + mi.Fields.Add(f2) + mi.Fields.Pk = fa + + mi.Uniques = []string{f1.Column, f2.Column} + return +} diff --git a/client/orm/models_utils.go b/client/orm/internal/models/models_utils.go similarity index 67% rename from client/orm/models_utils.go rename to client/orm/internal/models/models_utils.go index b2e5760e..b5204606 100644 --- a/client/orm/models_utils.go +++ b/client/orm/internal/models/models_utils.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package orm +package models import ( "database/sql" @@ -20,6 +20,8 @@ import ( "reflect" "strings" "time" + + "github.com/beego/beego/v2/client/orm/internal/logs" ) // 1 is attr @@ -48,15 +50,29 @@ var supportTag = map[string]int{ "precision": 2, } -// get reflect.Type name with package path. -func getFullName(typ reflect.Type) string { +type fn func(string) string + +var ( + NameStrategyMap = map[string]fn{ + DefaultNameStrategy: SnakeString, + SnakeAcronymNameStrategy: SnakeStringWithAcronym, + } + DefaultNameStrategy = "snakeString" + SnakeAcronymNameStrategy = "snakeStringWithAcronym" + NameStrategy = DefaultNameStrategy + defaultStructTagDelim = ";" + DefaultStructTagName = "orm" +) + +// GetFullName get reflect.Type name with package path. +func GetFullName(typ reflect.Type) string { return typ.PkgPath() + "." + typ.Name() } -// getTableName get struct table name. +// GetTableName get struct table name. // If the struct implement the TableName, then get the result as tablename // else use the struct name which will apply snakeString. -func getTableName(val reflect.Value) string { +func GetTableName(val reflect.Value) string { if fun := val.MethodByName("TableName"); fun.IsValid() { vals := fun.Call([]reflect.Value{}) // has return and the first val is string @@ -64,11 +80,11 @@ func getTableName(val reflect.Value) string { return vals[0].String() } } - return snakeString(reflect.Indirect(val).Type().Name()) + return SnakeString(reflect.Indirect(val).Type().Name()) } -// get table engine, myisam or innodb. -func getTableEngine(val reflect.Value) string { +// GetTableEngine get table engine, myisam or innodb. +func GetTableEngine(val reflect.Value) string { fun := val.MethodByName("TableEngine") if fun.IsValid() { vals := fun.Call([]reflect.Value{}) @@ -79,8 +95,8 @@ func getTableEngine(val reflect.Value) string { return "" } -// get table index from method. -func getTableIndex(val reflect.Value) [][]string { +// GetTableIndex get table index from method. +func GetTableIndex(val reflect.Value) [][]string { fun := val.MethodByName("TableIndex") if fun.IsValid() { vals := fun.Call([]reflect.Value{}) @@ -93,8 +109,8 @@ func getTableIndex(val reflect.Value) [][]string { return nil } -// get table unique from method -func getTableUnique(val reflect.Value) [][]string { +// GetTableUnique get table unique from method +func GetTableUnique(val reflect.Value) [][]string { fun := val.MethodByName("TableUnique") if fun.IsValid() { vals := fun.Call([]reflect.Value{}) @@ -107,8 +123,8 @@ func getTableUnique(val reflect.Value) [][]string { return nil } -// get whether the table needs to be created for the database alias -func isApplicableTableForDB(val reflect.Value, db string) bool { +// IsApplicableTableForDB get whether the table needs to be created for the database alias +func IsApplicableTableForDB(val reflect.Value, db string) bool { if !val.IsValid() { return true } @@ -126,7 +142,7 @@ func isApplicableTableForDB(val reflect.Value, db string) bool { func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col string) string { column := col if col == "" { - column = nameStrategyMap[nameStrategy](sf.Name) + column = NameStrategyMap[NameStrategy](sf.Name) } switch ft { case RelForeignKey, RelOneToOne: @@ -218,8 +234,8 @@ func getFieldType(val reflect.Value) (ft int, err error) { return } -// parse struct tag string -func parseStructTag(data string) (attrs map[string]bool, tags map[string]string) { +// ParseStructTag parse struct tag string +func ParseStructTag(data string) (attrs map[string]bool, tags map[string]string) { attrs = make(map[string]bool) tags = make(map[string]string) for _, v := range strings.Split(data, defaultStructTagDelim) { @@ -236,8 +252,74 @@ func parseStructTag(data string) (attrs map[string]bool, tags map[string]string) tags[name] = v } } else { - DebugLog.Println("unsupport orm tag", v) + logs.DebugLog.Println("unsupport orm tag", v) } } return } + +func SnakeStringWithAcronym(s string) string { + data := make([]byte, 0, len(s)*2) + num := len(s) + for i := 0; i < num; i++ { + d := s[i] + before := false + after := false + if i > 0 { + before = s[i-1] >= 'a' && s[i-1] <= 'z' + } + if i+1 < num { + after = s[i+1] >= 'a' && s[i+1] <= 'z' + } + if i > 0 && d >= 'A' && d <= 'Z' && (before || after) { + data = append(data, '_') + } + data = append(data, d) + } + return strings.ToLower(string(data)) +} + +// SnakeString snake string, XxYy to xx_yy , XxYY to xx_y_y +func SnakeString(s string) string { + data := make([]byte, 0, len(s)*2) + j := false + num := len(s) + for i := 0; i < num; i++ { + d := s[i] + if i > 0 && d >= 'A' && d <= 'Z' && j { + data = append(data, '_') + } + if d != '_' { + j = true + } + data = append(data, d) + } + return strings.ToLower(string(data)) +} + +// CamelString camel string, xx_yy to XxYy +func CamelString(s string) string { + data := make([]byte, 0, len(s)) + flag, num := true, len(s)-1 + for i := 0; i <= num; i++ { + d := s[i] + if d == '_' { + flag = true + continue + } else if flag { + if d >= 'a' && d <= 'z' { + d = d - 32 + } + flag = false + } + data = append(data, d) + } + return string(data) +} + +const ( + OdCascade = "cascade" + OdSetNULL = "set_null" + OdSetDefault = "set_default" + OdDoNothing = "do_nothing" +) diff --git a/client/orm/utils_test.go b/client/orm/internal/models/models_utils_test.go similarity index 75% rename from client/orm/utils_test.go rename to client/orm/internal/models/models_utils_test.go index 7d94cada..40bffc66 100644 --- a/client/orm/utils_test.go +++ b/client/orm/internal/models/models_utils_test.go @@ -1,10 +1,10 @@ -// Copyright 2014 beego Author. All Rights Reserved. +// Copyright 2020 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,27 +12,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -package orm +package models import ( + "reflect" "testing" + + "github.com/stretchr/testify/assert" ) -func TestCamelString(t *testing.T) { - snake := []string{"pic_url", "hello_world_", "hello__World", "_HelLO_Word", "pic_url_1", "pic_url__1"} - camel := []string{"PicUrl", "HelloWorld", "HelloWorld", "HelLOWord", "PicUrl1", "PicUrl1"} +type NotApplicableModel struct { + Id int +} - answer := make(map[string]string) - for i, v := range snake { - answer[v] = camel[i] - } +func (n *NotApplicableModel) IsApplicableTableForDB(db string) bool { + return db == "default" +} - for _, v := range snake { - res := camelString(v) - if res != answer[v] { - t.Error("Unit Test Fail:", v, res, answer[v]) - } - } +func TestIsApplicableTableForDB(t *testing.T) { + assert.False(t, IsApplicableTableForDB(reflect.ValueOf(&NotApplicableModel{}), "defa")) + assert.True(t, IsApplicableTableForDB(reflect.ValueOf(&NotApplicableModel{}), "default")) } func TestSnakeString(t *testing.T) { @@ -45,7 +44,7 @@ func TestSnakeString(t *testing.T) { } for _, v := range camel { - res := snakeString(v) + res := SnakeString(v) if res != answer[v] { t.Error("Unit Test Fail:", v, res, answer[v]) } @@ -62,7 +61,24 @@ func TestSnakeStringWithAcronym(t *testing.T) { } for _, v := range camel { - res := snakeStringWithAcronym(v) + res := SnakeStringWithAcronym(v) + if res != answer[v] { + t.Error("Unit Test Fail:", v, res, answer[v]) + } + } +} + +func TestCamelString(t *testing.T) { + snake := []string{"pic_url", "hello_world_", "hello__World", "_HelLO_Word", "pic_url_1", "pic_url__1"} + camel := []string{"PicUrl", "HelloWorld", "HelloWorld", "HelLOWord", "PicUrl1", "PicUrl1"} + + answer := make(map[string]string) + for i, v := range snake { + answer[v] = camel[i] + } + + for _, v := range snake { + res := CamelString(v) if res != answer[v] { t.Error("Unit Test Fail:", v, res, answer[v]) } diff --git a/adapter/config/json.go b/client/orm/internal/models/types.go similarity index 73% rename from adapter/config/json.go rename to client/orm/internal/models/types.go index b5a481cd..f3b7989a 100644 --- a/adapter/config/json.go +++ b/client/orm/internal/models/types.go @@ -1,4 +1,4 @@ -// Copyright 2014 beego Author. All Rights Reserved. +// Copyright 2023 beego-dev. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package config +package models -import ( - _ "github.com/beego/beego/v2/core/config/json" -) +// Fielder define field info +type Fielder interface { + String() string + FieldType() int + SetRaw(interface{}) error + RawValue() interface{} +} diff --git a/client/orm/internal/utils/utils.go b/client/orm/internal/utils/utils.go new file mode 100644 index 00000000..5e338487 --- /dev/null +++ b/client/orm/internal/utils/utils.go @@ -0,0 +1,249 @@ +// Copyright 2014 beego Author. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "fmt" + "math/big" + "reflect" + "strconv" + "time" +) + +// StrTo is the target string +type StrTo string + +// Set string +func (f *StrTo) Set(v string) { + if v != "" { + *f = StrTo(v) + } else { + f.Clear() + } +} + +// Clear string +func (f *StrTo) Clear() { + *f = StrTo(rune(0x1E)) +} + +// Exist check string exist +func (f StrTo) Exist() bool { + return string(f) != string(rune(0x1E)) +} + +// Bool string to bool +func (f StrTo) Bool() (bool, error) { + return strconv.ParseBool(f.String()) +} + +// Float32 string to float32 +func (f StrTo) Float32() (float32, error) { + v, err := strconv.ParseFloat(f.String(), 32) + return float32(v), err +} + +// Float64 string to float64 +func (f StrTo) Float64() (float64, error) { + return strconv.ParseFloat(f.String(), 64) +} + +// Int string to int +func (f StrTo) Int() (int, error) { + v, err := strconv.ParseInt(f.String(), 10, 32) + return int(v), err +} + +// Int8 string to int8 +func (f StrTo) Int8() (int8, error) { + v, err := strconv.ParseInt(f.String(), 10, 8) + return int8(v), err +} + +// Int16 string to int16 +func (f StrTo) Int16() (int16, error) { + v, err := strconv.ParseInt(f.String(), 10, 16) + return int16(v), err +} + +// Int32 string to int32 +func (f StrTo) Int32() (int32, error) { + v, err := strconv.ParseInt(f.String(), 10, 32) + return int32(v), err +} + +// Int64 string to int64 +func (f StrTo) Int64() (int64, error) { + v, err := strconv.ParseInt(f.String(), 10, 64) + if err != nil { + i := new(big.Int) + ni, ok := i.SetString(f.String(), 10) // octal + if !ok { + return v, err + } + return ni.Int64(), nil + } + return v, err +} + +// Uint string to uint +func (f StrTo) Uint() (uint, error) { + v, err := strconv.ParseUint(f.String(), 10, 32) + return uint(v), err +} + +// Uint8 string to uint8 +func (f StrTo) Uint8() (uint8, error) { + v, err := strconv.ParseUint(f.String(), 10, 8) + return uint8(v), err +} + +// Uint16 string to uint16 +func (f StrTo) Uint16() (uint16, error) { + v, err := strconv.ParseUint(f.String(), 10, 16) + return uint16(v), err +} + +// Uint32 string to uint32 +func (f StrTo) Uint32() (uint32, error) { + v, err := strconv.ParseUint(f.String(), 10, 32) + return uint32(v), err +} + +// Uint64 string to uint64 +func (f StrTo) Uint64() (uint64, error) { + v, err := strconv.ParseUint(f.String(), 10, 64) + if err != nil { + i := new(big.Int) + ni, ok := i.SetString(f.String(), 10) + if !ok { + return v, err + } + return ni.Uint64(), nil + } + return v, err +} + +// String string to string +func (f StrTo) String() string { + if f.Exist() { + return string(f) + } + return "" +} + +// ToStr interface to string +func ToStr(value interface{}, args ...int) (s string) { + switch v := value.(type) { + case bool: + s = strconv.FormatBool(v) + case float32: + s = strconv.FormatFloat(float64(v), 'f', ArgInt(args).Get(0, -1), ArgInt(args).Get(1, 32)) + case float64: + s = strconv.FormatFloat(v, 'f', ArgInt(args).Get(0, -1), ArgInt(args).Get(1, 64)) + case int: + s = strconv.FormatInt(int64(v), ArgInt(args).Get(0, 10)) + case int8: + s = strconv.FormatInt(int64(v), ArgInt(args).Get(0, 10)) + case int16: + s = strconv.FormatInt(int64(v), ArgInt(args).Get(0, 10)) + case int32: + s = strconv.FormatInt(int64(v), ArgInt(args).Get(0, 10)) + case int64: + s = strconv.FormatInt(v, ArgInt(args).Get(0, 10)) + case uint: + s = strconv.FormatUint(uint64(v), ArgInt(args).Get(0, 10)) + case uint8: + s = strconv.FormatUint(uint64(v), ArgInt(args).Get(0, 10)) + case uint16: + s = strconv.FormatUint(uint64(v), ArgInt(args).Get(0, 10)) + case uint32: + s = strconv.FormatUint(uint64(v), ArgInt(args).Get(0, 10)) + case uint64: + s = strconv.FormatUint(v, ArgInt(args).Get(0, 10)) + case string: + s = v + case []byte: + s = string(v) + default: + s = fmt.Sprintf("%v", v) + } + return s +} + +// ToInt64 interface to int64 +func ToInt64(value interface{}) (d int64) { + val := reflect.ValueOf(value) + switch value.(type) { + case int, int8, int16, int32, int64: + d = val.Int() + case uint, uint8, uint16, uint32, uint64: + d = int64(val.Uint()) + default: + panic(fmt.Errorf("ToInt64 need numeric not `%T`", value)) + } + return +} + +type ArgString []string + +// Get get string by index from string slice +func (a ArgString) Get(i int, args ...string) (r string) { + if i >= 0 && i < len(a) { + r = a[i] + } else if len(args) > 0 { + r = args[0] + } + return +} + +type ArgInt []int + +// Get get int by index from int slice +func (a ArgInt) Get(i int, args ...int) (r int) { + if i >= 0 && i < len(a) { + r = a[i] + } + if len(args) > 0 { + r = args[0] + } + return +} + +// TimeParse parse time to string with location +func TimeParse(dateString, format string) (time.Time, error) { + tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) + return tp, err +} + +// IndirectType get pointer indirect type +func IndirectType(v reflect.Type) reflect.Type { + switch v.Kind() { + case reflect.Ptr: + return IndirectType(v.Elem()) + default: + return v + } +} + +const ( + FormatTime = "15:04:05" + FormatDate = "2006-01-02" + FormatDateTime = "2006-01-02 15:04:05" +) + +var ( + DefaultTimeLoc = time.Local +) diff --git a/client/orm/invocation.go b/client/orm/invocation.go index 9e7c1974..48fdbf6e 100644 --- a/client/orm/invocation.go +++ b/client/orm/invocation.go @@ -17,6 +17,8 @@ package orm import ( "context" "time" + + "github.com/beego/beego/v2/client/orm/internal/models" ) // Invocation represents an "Orm" invocation @@ -27,7 +29,7 @@ type Invocation struct { // the args are all arguments except context.Context Args []interface{} - mi *modelInfo + mi *models.ModelInfo // f is the Orm operation f func(ctx context.Context) []interface{} @@ -39,7 +41,7 @@ type Invocation struct { func (inv *Invocation) GetTableName() string { if inv.mi != nil { - return inv.mi.table + return inv.mi.Table } return "" } @@ -51,8 +53,8 @@ func (inv *Invocation) execute(ctx context.Context) []interface{} { // GetPkFieldName return the primary key of this table // if not found, "" is returned func (inv *Invocation) GetPkFieldName() string { - if inv.mi.fields.pk != nil { - return inv.mi.fields.pk.name + if inv.mi.Fields.Pk != nil { + return inv.mi.Fields.Pk.Name } return "" } diff --git a/client/orm/migration/ddl.go b/client/orm/migration/ddl.go index ab452b49..bcbfdd5a 100644 --- a/client/orm/migration/ddl.go +++ b/client/orm/migration/ddl.go @@ -274,7 +274,7 @@ func (m *Migration) GetSQL() (sql string) { } if len(m.Primary) > 0 { - sql += fmt.Sprintf(",\n PRIMARY KEY( ") + sql += ",\n PRIMARY KEY( " } for index, column := range m.Primary { sql += fmt.Sprintf(" `%s`", column.Name) @@ -284,7 +284,7 @@ func (m *Migration) GetSQL() (sql string) { } if len(m.Primary) > 0 { - sql += fmt.Sprintf(")") + sql += ")" } for _, unique := range m.Uniques { @@ -295,7 +295,7 @@ func (m *Migration) GetSQL() (sql string) { sql += "," } } - sql += fmt.Sprintf(")") + sql += ")" } for _, foreign := range m.Foreigns { sql += fmt.Sprintf(",\n `%s` %s %s %s %s %s", foreign.Name, foreign.DataType, foreign.Unsign, foreign.Null, foreign.Inc, foreign.Default) @@ -356,7 +356,7 @@ func (m *Migration) GetSQL() (sql string) { } if len(m.Primary) > 0 { - sql += fmt.Sprintf("\n DROP PRIMARY KEY,") + sql += "\n DROP PRIMARY KEY," } for index, unique := range m.Uniques { diff --git a/client/orm/mock/mock_orm.go b/client/orm/mock/mock_orm.go index ce6712a4..77fe2496 100644 --- a/client/orm/mock/mock_orm.go +++ b/client/orm/mock/mock_orm.go @@ -106,8 +106,10 @@ func MockDeleteWithCtx(tableName string, affectedRow int64, err error) *Mock { // Now you may be need to use golang/mock to generate QueryM2M mock instance // Or use DoNothingQueryM2Mer // for example: -// post := Post{Id: 4} -// m2m := Ormer.QueryM2M(&post, "Tags") +// +// post := Post{Id: 4} +// m2m := Ormer.QueryM2M(&post, "Tags") +// // when you write test code: // MockQueryM2MWithCtx("post", "Tags", mockM2Mer) // "post" is the table name of model Post structure diff --git a/client/orm/model_utils_test.go b/client/orm/model_utils_test.go index be97c58d..d3d57cdf 100644 --- a/client/orm/model_utils_test.go +++ b/client/orm/model_utils_test.go @@ -17,6 +17,8 @@ package orm import ( "testing" + "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/stretchr/testify/assert" ) @@ -53,10 +55,10 @@ func TestDbBase_GetTables(t *testing.T) { assert.True(t, ok) assert.NotNil(t, mi) - engine := getTableEngine(mi.addrField) + engine := models.GetTableEngine(mi.AddrField) assert.Equal(t, "innodb", engine) - uniques := getTableUnique(mi.addrField) + uniques := models.GetTableUnique(mi.AddrField) assert.Equal(t, [][]string{{"unique1"}, {"unique2"}}, uniques) - indexes := getTableIndex(mi.addrField) + indexes := models.GetTableIndex(mi.AddrField) assert.Equal(t, [][]string{{"index1"}, {"index2"}}, indexes) } diff --git a/client/orm/models.go b/client/orm/models.go index 94630ba5..542ced59 100644 --- a/client/orm/models.go +++ b/client/orm/models.go @@ -21,15 +21,8 @@ import ( "runtime/debug" "strings" "sync" -) -const ( - odCascade = "cascade" - odSetNULL = "set_null" - odSetDefault = "set_default" - odDoNothing = "do_nothing" - defaultStructTagName = "orm" - defaultStructTagDelim = ";" + imodels "github.com/beego/beego/v2/client/orm/internal/models" ) var defaultModelCache = NewModelCacheHandler() @@ -38,22 +31,22 @@ var defaultModelCache = NewModelCacheHandler() type modelCache struct { sync.RWMutex // only used outsite for bootStrap orders []string - cache map[string]*modelInfo - cacheByFullName map[string]*modelInfo + cache map[string]*imodels.ModelInfo + cacheByFullName map[string]*imodels.ModelInfo done bool } // NewModelCacheHandler generator of modelCache func NewModelCacheHandler() *modelCache { return &modelCache{ - cache: make(map[string]*modelInfo), - cacheByFullName: make(map[string]*modelInfo), + cache: make(map[string]*imodels.ModelInfo), + cacheByFullName: make(map[string]*imodels.ModelInfo), } } // get all model info -func (mc *modelCache) all() map[string]*modelInfo { - m := make(map[string]*modelInfo, len(mc.cache)) +func (mc *modelCache) all() map[string]*imodels.ModelInfo { + m := make(map[string]*imodels.ModelInfo, len(mc.cache)) for k, v := range mc.cache { m[k] = v } @@ -61,8 +54,8 @@ func (mc *modelCache) all() map[string]*modelInfo { } // get ordered model info -func (mc *modelCache) allOrdered() []*modelInfo { - m := make([]*modelInfo, 0, len(mc.orders)) +func (mc *modelCache) allOrdered() []*imodels.ModelInfo { + m := make([]*imodels.ModelInfo, 0, len(mc.orders)) for _, table := range mc.orders { m = append(m, mc.cache[table]) } @@ -70,30 +63,30 @@ func (mc *modelCache) allOrdered() []*modelInfo { } // get model info by table name -func (mc *modelCache) get(table string) (mi *modelInfo, ok bool) { +func (mc *modelCache) get(table string) (mi *imodels.ModelInfo, ok bool) { mi, ok = mc.cache[table] return } // get model info by full name -func (mc *modelCache) getByFullName(name string) (mi *modelInfo, ok bool) { +func (mc *modelCache) getByFullName(name string) (mi *imodels.ModelInfo, ok bool) { mi, ok = mc.cacheByFullName[name] return } -func (mc *modelCache) getByMd(md interface{}) (*modelInfo, bool) { +func (mc *modelCache) getByMd(md interface{}) (*imodels.ModelInfo, bool) { val := reflect.ValueOf(md) ind := reflect.Indirect(val) typ := ind.Type() - name := getFullName(typ) + name := imodels.GetFullName(typ) return mc.getByFullName(name) } // set model info to collection -func (mc *modelCache) set(table string, mi *modelInfo) *modelInfo { +func (mc *modelCache) set(table string, mi *imodels.ModelInfo) *imodels.ModelInfo { mii := mc.cache[table] mc.cache[table] = mi - mc.cacheByFullName[mi.fullName] = mi + mc.cacheByFullName[mi.FullName] = mi if mii == nil { mc.orders = append(mc.orders, table) } @@ -106,8 +99,8 @@ func (mc *modelCache) clean() { defer mc.Unlock() mc.orders = make([]string, 0) - mc.cache = make(map[string]*modelInfo) - mc.cacheByFullName = make(map[string]*modelInfo) + mc.cache = make(map[string]*imodels.ModelInfo) + mc.cacheByFullName = make(map[string]*imodels.ModelInfo) mc.done = false } @@ -120,7 +113,7 @@ func (mc *modelCache) bootstrap() { } var ( err error - models map[string]*modelInfo + models map[string]*imodels.ModelInfo ) if dataBaseCache.getDefault() == nil { err = fmt.Errorf("must have one register DataBase alias named `default`") @@ -131,51 +124,51 @@ func (mc *modelCache) bootstrap() { // RelManyToMany set the relTable models = mc.all() for _, mi := range models { - for _, fi := range mi.fields.columns { - if fi.rel || fi.reverse { - elm := fi.addrValue.Type().Elem() - if fi.fieldType == RelReverseMany || fi.fieldType == RelManyToMany { + for _, fi := range mi.Fields.Columns { + if fi.Rel || fi.Reverse { + elm := fi.AddrValue.Type().Elem() + if fi.FieldType == RelReverseMany || fi.FieldType == RelManyToMany { elm = elm.Elem() } // check the rel or reverse model already register - name := getFullName(elm) + name := imodels.GetFullName(elm) mii, ok := mc.getByFullName(name) - if !ok || mii.pkg != elm.PkgPath() { - err = fmt.Errorf("can not find rel in field `%s`, `%s` may be miss register", fi.fullName, elm.String()) + if !ok || mii.Pkg != elm.PkgPath() { + err = fmt.Errorf("can not find rel in field `%s`, `%s` may be miss register", fi.FullName, elm.String()) goto end } - fi.relModelInfo = mii + fi.RelModelInfo = mii - switch fi.fieldType { + switch fi.FieldType { case RelManyToMany: - if fi.relThrough != "" { - if i := strings.LastIndex(fi.relThrough, "."); i != -1 && len(fi.relThrough) > (i+1) { - pn := fi.relThrough[:i] - rmi, ok := mc.getByFullName(fi.relThrough) - if !ok || pn != rmi.pkg { - err = fmt.Errorf("field `%s` wrong rel_through value `%s` cannot find table", fi.fullName, fi.relThrough) + if fi.RelThrough != "" { + if i := strings.LastIndex(fi.RelThrough, "."); i != -1 && len(fi.RelThrough) > (i+1) { + pn := fi.RelThrough[:i] + rmi, ok := mc.getByFullName(fi.RelThrough) + if !ok || pn != rmi.Pkg { + err = fmt.Errorf("field `%s` wrong rel_through value `%s` cannot find table", fi.FullName, fi.RelThrough) goto end } - fi.relThroughModelInfo = rmi - fi.relTable = rmi.table + fi.RelThroughModelInfo = rmi + fi.RelTable = rmi.Table } else { - err = fmt.Errorf("field `%s` wrong rel_through value `%s`", fi.fullName, fi.relThrough) + err = fmt.Errorf("field `%s` wrong rel_through value `%s`", fi.FullName, fi.RelThrough) goto end } } else { - i := newM2MModelInfo(mi, mii) - if fi.relTable != "" { - i.table = fi.relTable + i := imodels.NewM2MModelInfo(mi, mii) + if fi.RelTable != "" { + i.Table = fi.RelTable } - if v := mc.set(i.table, i); v != nil { - err = fmt.Errorf("the rel table name `%s` already registered, cannot be use, please change one", fi.relTable) + if v := mc.set(i.Table, i); v != nil { + err = fmt.Errorf("the rel table name `%s` already registered, cannot be use, please change one", fi.RelTable) goto end } - fi.relTable = i.table - fi.relThroughModelInfo = i + fi.RelTable = i.Table + fi.RelThroughModelInfo = i } - fi.relThroughModelInfo.isThrough = true + fi.RelThroughModelInfo.IsThrough = true } } } @@ -185,42 +178,42 @@ func (mc *modelCache) bootstrap() { // if not exist, add a new field to the relModelInfo models = mc.all() for _, mi := range models { - for _, fi := range mi.fields.fieldsRel { - switch fi.fieldType { + for _, fi := range mi.Fields.FieldsRel { + switch fi.FieldType { case RelForeignKey, RelOneToOne, RelManyToMany: inModel := false - for _, ffi := range fi.relModelInfo.fields.fieldsReverse { - if ffi.relModelInfo == mi { + for _, ffi := range fi.RelModelInfo.Fields.FieldsReverse { + if ffi.RelModelInfo == mi { inModel = true break } } if !inModel { - rmi := fi.relModelInfo - ffi := new(fieldInfo) - ffi.name = mi.name - ffi.column = ffi.name - ffi.fullName = rmi.fullName + "." + ffi.name - ffi.reverse = true - ffi.relModelInfo = mi - ffi.mi = rmi - if fi.fieldType == RelOneToOne { - ffi.fieldType = RelReverseOne + rmi := fi.RelModelInfo + ffi := new(imodels.FieldInfo) + ffi.Name = mi.Name + ffi.Column = ffi.Name + ffi.FullName = rmi.FullName + "." + ffi.Name + ffi.Reverse = true + ffi.RelModelInfo = mi + ffi.Mi = rmi + if fi.FieldType == RelOneToOne { + ffi.FieldType = RelReverseOne } else { - ffi.fieldType = RelReverseMany + ffi.FieldType = RelReverseMany } - if !rmi.fields.Add(ffi) { + if !rmi.Fields.Add(ffi) { added := false for cnt := 0; cnt < 5; cnt++ { - ffi.name = fmt.Sprintf("%s%d", mi.name, cnt) - ffi.column = ffi.name - ffi.fullName = rmi.fullName + "." + ffi.name - if added = rmi.fields.Add(ffi); added { + ffi.Name = fmt.Sprintf("%s%d", mi.Name, cnt) + ffi.Column = ffi.Name + ffi.FullName = rmi.FullName + "." + ffi.Name + if added = rmi.Fields.Add(ffi); added { break } } if !added { - panic(fmt.Errorf("cannot generate auto reverse field info `%s` to `%s`", fi.fullName, ffi.fullName)) + panic(fmt.Errorf("cannot generate auto reverse field info `%s` to `%s`", fi.FullName, ffi.FullName)) } } } @@ -230,24 +223,24 @@ func (mc *modelCache) bootstrap() { models = mc.all() for _, mi := range models { - for _, fi := range mi.fields.fieldsRel { - switch fi.fieldType { + for _, fi := range mi.Fields.FieldsRel { + switch fi.FieldType { case RelManyToMany: - for _, ffi := range fi.relThroughModelInfo.fields.fieldsRel { - switch ffi.fieldType { + for _, ffi := range fi.RelThroughModelInfo.Fields.FieldsRel { + switch ffi.FieldType { case RelOneToOne, RelForeignKey: - if ffi.relModelInfo == fi.relModelInfo { - fi.reverseFieldInfoTwo = ffi + if ffi.RelModelInfo == fi.RelModelInfo { + fi.ReverseFieldInfoTwo = ffi } - if ffi.relModelInfo == mi { - fi.reverseField = ffi.name - fi.reverseFieldInfo = ffi + if ffi.RelModelInfo == mi { + fi.ReverseField = ffi.Name + fi.ReverseFieldInfo = ffi } } } - if fi.reverseFieldInfoTwo == nil { + if fi.ReverseFieldInfoTwo == nil { err = fmt.Errorf("can not find m2m field for m2m model `%s`, ensure your m2m model defined correct", - fi.relThroughModelInfo.fullName) + fi.RelThroughModelInfo.FullName) goto end } } @@ -256,63 +249,63 @@ func (mc *modelCache) bootstrap() { models = mc.all() for _, mi := range models { - for _, fi := range mi.fields.fieldsReverse { - switch fi.fieldType { + for _, fi := range mi.Fields.FieldsReverse { + switch fi.FieldType { case RelReverseOne: found := false mForA: - for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelOneToOne] { - if ffi.relModelInfo == mi { + for _, ffi := range fi.RelModelInfo.Fields.FieldsByType[RelOneToOne] { + if ffi.RelModelInfo == mi { found = true - fi.reverseField = ffi.name - fi.reverseFieldInfo = ffi + fi.ReverseField = ffi.Name + fi.ReverseFieldInfo = ffi - ffi.reverseField = fi.name - ffi.reverseFieldInfo = fi + ffi.ReverseField = fi.Name + ffi.ReverseFieldInfo = fi break mForA } } if !found { - err = fmt.Errorf("reverse field `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName) + err = fmt.Errorf("reverse field `%s` not found in model `%s`", fi.FullName, fi.RelModelInfo.FullName) goto end } case RelReverseMany: found := false mForB: - for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelForeignKey] { - if ffi.relModelInfo == mi { + for _, ffi := range fi.RelModelInfo.Fields.FieldsByType[RelForeignKey] { + if ffi.RelModelInfo == mi { found = true - fi.reverseField = ffi.name - fi.reverseFieldInfo = ffi + fi.ReverseField = ffi.Name + fi.ReverseFieldInfo = ffi - ffi.reverseField = fi.name - ffi.reverseFieldInfo = fi + ffi.ReverseField = fi.Name + ffi.ReverseFieldInfo = fi break mForB } } if !found { mForC: - for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelManyToMany] { - conditions := fi.relThrough != "" && fi.relThrough == ffi.relThrough || - fi.relTable != "" && fi.relTable == ffi.relTable || - fi.relThrough == "" && fi.relTable == "" - if ffi.relModelInfo == mi && conditions { + for _, ffi := range fi.RelModelInfo.Fields.FieldsByType[RelManyToMany] { + conditions := fi.RelThrough != "" && fi.RelThrough == ffi.RelThrough || + fi.RelTable != "" && fi.RelTable == ffi.RelTable || + fi.RelThrough == "" && fi.RelTable == "" + if ffi.RelModelInfo == mi && conditions { found = true - fi.reverseField = ffi.reverseFieldInfoTwo.name - fi.reverseFieldInfo = ffi.reverseFieldInfoTwo - fi.relThroughModelInfo = ffi.relThroughModelInfo - fi.reverseFieldInfoTwo = ffi.reverseFieldInfo - fi.reverseFieldInfoM2M = ffi - ffi.reverseFieldInfoM2M = fi + fi.ReverseField = ffi.ReverseFieldInfoTwo.Name + fi.ReverseFieldInfo = ffi.ReverseFieldInfoTwo + fi.RelThroughModelInfo = ffi.RelThroughModelInfo + fi.ReverseFieldInfoTwo = ffi.ReverseFieldInfo + fi.ReverseFieldInfoM2M = ffi + ffi.ReverseFieldInfoM2M = fi break mForC } } } if !found { - err = fmt.Errorf("reverse field for `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName) + err = fmt.Errorf("reverse field for `%s` not found in model `%s`", fi.FullName, fi.RelModelInfo.FullName) goto end } } @@ -334,7 +327,7 @@ func (mc *modelCache) register(prefixOrSuffixStr string, prefixOrSuffix bool, mo typ := reflect.Indirect(val).Type() if val.Kind() != reflect.Ptr { - err = fmt.Errorf(" cannot use non-ptr model struct `%s`", getFullName(typ)) + err = fmt.Errorf(" cannot use non-ptr model struct `%s`", imodels.GetFullName(typ)) return } // For this case: @@ -347,7 +340,7 @@ func (mc *modelCache) register(prefixOrSuffixStr string, prefixOrSuffix bool, mo if val.Elem().Kind() == reflect.Slice { val = reflect.New(val.Elem().Type().Elem()) } - table := getTableName(val) + table := imodels.GetTableName(val) if prefixOrSuffixStr != "" { if prefixOrSuffix { @@ -358,7 +351,7 @@ func (mc *modelCache) register(prefixOrSuffixStr string, prefixOrSuffix bool, mo } // models's fullname is pkgpath + struct name - name := getFullName(typ) + name := imodels.GetFullName(typ) if _, ok := mc.getByFullName(name); ok { err = fmt.Errorf(" model `%s` repeat register, must be unique\n", name) return @@ -368,26 +361,26 @@ func (mc *modelCache) register(prefixOrSuffixStr string, prefixOrSuffix bool, mo return nil } - mi := newModelInfo(val) - if mi.fields.pk == nil { + mi := imodels.NewModelInfo(val) + if mi.Fields.Pk == nil { outFor: - for _, fi := range mi.fields.fieldsDB { - if strings.ToLower(fi.name) == "id" { - switch fi.addrValue.Elem().Kind() { + for _, fi := range mi.Fields.FieldsDB { + if strings.ToLower(fi.Name) == "id" { + switch fi.AddrValue.Elem().Kind() { case reflect.Int, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint32, reflect.Uint64: - fi.auto = true - fi.pk = true - mi.fields.pk = fi + fi.Auto = true + fi.Pk = true + mi.Fields.Pk = fi break outFor } } } } - mi.table = table - mi.pkg = typ.PkgPath() - mi.model = model - mi.manual = true + mi.Table = table + mi.Pkg = typ.PkgPath() + mi.Model = model + mi.Manual = true mc.set(table, mi) } @@ -404,7 +397,7 @@ func (mc *modelCache) getDbDropSQL(al *alias) (queries []string, err error) { Q := al.DbBaser.TableQuote() for _, mi := range mc.allOrdered() { - queries = append(queries, fmt.Sprintf(`DROP TABLE IF EXISTS %s%s%s`, Q, mi.table, Q)) + queries = append(queries, fmt.Sprintf(`DROP TABLE IF EXISTS %s%s%s`, Q, mi.Table, Q)) } return queries, nil } @@ -424,33 +417,33 @@ func (mc *modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes for _, mi := range mc.allOrdered() { sql := fmt.Sprintf("-- %s\n", strings.Repeat("-", 50)) - sql += fmt.Sprintf("-- Table Structure for `%s`\n", mi.fullName) + sql += fmt.Sprintf("-- Table Structure for `%s`\n", mi.FullName) sql += fmt.Sprintf("-- %s\n", strings.Repeat("-", 50)) - sql += fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s%s%s (\n", Q, mi.table, Q) + sql += fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s%s%s (\n", Q, mi.Table, Q) - columns := make([]string, 0, len(mi.fields.fieldsDB)) + columns := make([]string, 0, len(mi.Fields.FieldsDB)) sqlIndexes := [][]string{} var commentIndexes []int // store comment indexes for postgres - for i, fi := range mi.fields.fieldsDB { - column := fmt.Sprintf(" %s%s%s ", Q, fi.column, Q) + for i, fi := range mi.Fields.FieldsDB { + column := fmt.Sprintf(" %s%s%s ", Q, fi.Column, Q) col := getColumnTyp(al, fi) - if fi.auto { + if fi.Auto { switch al.Driver { case DRSqlite, DRPostgres: column += T["auto"] default: column += col + " " + T["auto"] } - } else if fi.pk { + } else if fi.Pk { column += col + " " + T["pk"] } else { column += col - if !fi.null { + if !fi.Null { column += " " + "NOT NULL" } @@ -461,42 +454,42 @@ func (mc *modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes // Append attribute DEFAULT column += getColumnDefault(fi) - if fi.unique { + if fi.Unique { column += " " + "UNIQUE" } - if fi.index { - sqlIndexes = append(sqlIndexes, []string{fi.column}) + if fi.Index { + sqlIndexes = append(sqlIndexes, []string{fi.Column}) } } if strings.Contains(column, "%COL%") { - column = strings.Replace(column, "%COL%", fi.column, -1) + column = strings.Replace(column, "%COL%", fi.Column, -1) } - if fi.description != "" && al.Driver != DRSqlite { + if fi.Description != "" && al.Driver != DRSqlite { if al.Driver == DRPostgres { commentIndexes = append(commentIndexes, i) } else { - column += " " + fmt.Sprintf("COMMENT '%s'", fi.description) + column += " " + fmt.Sprintf("COMMENT '%s'", fi.Description) } } columns = append(columns, column) } - if mi.model != nil { - allnames := getTableUnique(mi.addrField) - if !mi.manual && len(mi.uniques) > 0 { - allnames = append(allnames, mi.uniques) + if mi.Model != nil { + allnames := imodels.GetTableUnique(mi.AddrField) + if !mi.Manual && len(mi.Uniques) > 0 { + allnames = append(allnames, mi.Uniques) } for _, names := range allnames { cols := make([]string, 0, len(names)) for _, name := range names { - if fi, ok := mi.fields.GetByAny(name); ok && fi.dbcol { - cols = append(cols, fi.column) + if fi, ok := mi.Fields.GetByAny(name); ok && fi.DBcol { + cols = append(cols, fi.Column) } else { - panic(fmt.Errorf("cannot found column `%s` when parse UNIQUE in `%s.TableUnique`", name, mi.fullName)) + panic(fmt.Errorf("cannot found column `%s` when parse UNIQUE in `%s.TableUnique`", name, mi.FullName)) } } column := fmt.Sprintf(" UNIQUE (%s%s%s)", Q, strings.Join(cols, sep), Q) @@ -509,8 +502,8 @@ func (mc *modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes if al.Driver == DRMySQL { var engine string - if mi.model != nil { - engine = getTableEngine(mi.addrField) + if mi.Model != nil { + engine = imodels.GetTableEngine(mi.AddrField) } if engine == "" { engine = al.Engine @@ -524,24 +517,24 @@ func (mc *modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes for _, index := range commentIndexes { sql += fmt.Sprintf("\nCOMMENT ON COLUMN %s%s%s.%s%s%s is '%s';", Q, - mi.table, + mi.Table, Q, Q, - mi.fields.fieldsDB[index].column, + mi.Fields.FieldsDB[index].Column, Q, - mi.fields.fieldsDB[index].description) + mi.Fields.FieldsDB[index].Description) } } queries = append(queries, sql) - if mi.model != nil { - for _, names := range getTableIndex(mi.addrField) { + if mi.Model != nil { + for _, names := range imodels.GetTableIndex(mi.AddrField) { cols := make([]string, 0, len(names)) for _, name := range names { - if fi, ok := mi.fields.GetByAny(name); ok && fi.dbcol { - cols = append(cols, fi.column) + if fi, ok := mi.Fields.GetByAny(name); ok && fi.DBcol { + cols = append(cols, fi.Column) } else { - panic(fmt.Errorf("cannot found column `%s` when parse INDEX in `%s.TableIndex`", name, mi.fullName)) + panic(fmt.Errorf("cannot found column `%s` when parse INDEX in `%s.TableIndex`", name, mi.FullName)) } } sqlIndexes = append(sqlIndexes, cols) @@ -549,16 +542,16 @@ func (mc *modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes } for _, names := range sqlIndexes { - name := mi.table + "_" + strings.Join(names, "_") + name := mi.Table + "_" + strings.Join(names, "_") cols := strings.Join(names, sep) - sql := fmt.Sprintf("CREATE INDEX %s%s%s ON %s%s%s (%s%s%s);", Q, name, Q, Q, mi.table, Q, Q, cols, Q) + sql := fmt.Sprintf("CREATE INDEX %s%s%s ON %s%s%s (%s%s%s);", Q, name, Q, Q, mi.Table, Q, Q, cols, Q) index := dbIndex{} - index.Table = mi.table + index.Table = mi.Table index.Name = name index.SQL = sql - tableIndexes[mi.table] = append(tableIndexes[mi.table], index) + tableIndexes[mi.Table] = append(tableIndexes[mi.Table], index) } } diff --git a/client/orm/models_fields.go b/client/orm/models_fields.go index b4fad94f..4f07ea18 100644 --- a/client/orm/models_fields.go +++ b/client/orm/models_fields.go @@ -15,91 +15,47 @@ package orm import ( - "fmt" - "strconv" - "time" + "github.com/beego/beego/v2/client/orm/internal/models" ) // Define the Type enum const ( - TypeBooleanField = 1 << iota - TypeVarCharField - TypeCharField - TypeTextField - TypeTimeField - TypeDateField - TypeDateTimeField - TypeBitField - TypeSmallIntegerField - TypeIntegerField - TypeBigIntegerField - TypePositiveBitField - TypePositiveSmallIntegerField - TypePositiveIntegerField - TypePositiveBigIntegerField - TypeFloatField - TypeDecimalField - TypeJSONField - TypeJsonbField - RelForeignKey - RelOneToOne - RelManyToMany - RelReverseOne - RelReverseMany + TypeBooleanField = models.TypeBooleanField + TypeVarCharField = models.TypeVarCharField + TypeCharField = models.TypeCharField + TypeTextField = models.TypeTextField + TypeTimeField = models.TypeTimeField + TypeDateField = models.TypeDateField + TypeDateTimeField = models.TypeDateTimeField + TypeBitField = models.TypeBitField + TypeSmallIntegerField = models.TypeSmallIntegerField + TypeIntegerField = models.TypeIntegerField + TypeBigIntegerField = models.TypeBigIntegerField + TypePositiveBitField = models.TypePositiveBitField + TypePositiveSmallIntegerField = models.TypePositiveSmallIntegerField + TypePositiveIntegerField = models.TypePositiveIntegerField + TypePositiveBigIntegerField = models.TypePositiveBigIntegerField + TypeFloatField = models.TypeFloatField + TypeDecimalField = models.TypeDecimalField + TypeJSONField = models.TypeJSONField + TypeJsonbField = models.TypeJsonbField + RelForeignKey = models.RelForeignKey + RelOneToOne = models.RelOneToOne + RelManyToMany = models.RelManyToMany + RelReverseOne = models.RelReverseOne + RelReverseMany = models.RelReverseMany ) // Define some logic enum const ( - IsIntegerField = ^-TypePositiveBigIntegerField >> 6 << 7 - IsPositiveIntegerField = ^-TypePositiveBigIntegerField >> 10 << 11 - IsRelField = ^-RelReverseMany >> 18 << 19 - IsFieldType = ^-RelReverseMany<<1 + 1 + IsIntegerField = models.IsIntegerField + IsPositiveIntegerField = models.IsPositiveIntegerField + IsRelField = models.IsRelField + IsFieldType = models.IsFieldType ) // BooleanField A true/false field. -type BooleanField bool - -// Value return the BooleanField -func (e BooleanField) Value() bool { - return bool(e) -} - -// Set will set the BooleanField -func (e *BooleanField) Set(d bool) { - *e = BooleanField(d) -} - -// String format the Bool to string -func (e *BooleanField) String() string { - return strconv.FormatBool(e.Value()) -} - -// FieldType return BooleanField the type -func (e *BooleanField) FieldType() int { - return TypeBooleanField -} - -// SetRaw set the interface to bool -func (e *BooleanField) SetRaw(value interface{}) error { - switch d := value.(type) { - case bool: - e.Set(d) - case string: - v, err := StrTo(d).Bool() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return the current value -func (e *BooleanField) RawValue() interface{} { - return e.Value() -} +type BooleanField = models.BooleanField // verify the BooleanField implement the Fielder interface var _ Fielder = new(BooleanField) @@ -108,43 +64,7 @@ var _ Fielder = new(BooleanField) // required values tag: size // The size is enforced at the database level and in models’s validation. // eg: `orm:"size(120)"` -type CharField string - -// Value return the CharField's Value -func (e CharField) Value() string { - return string(e) -} - -// Set CharField value -func (e *CharField) Set(d string) { - *e = CharField(d) -} - -// String return the CharField -func (e *CharField) String() string { - return e.Value() -} - -// FieldType return the enum type -func (e *CharField) FieldType() int { - return TypeVarCharField -} - -// SetRaw set the interface to string -func (e *CharField) SetRaw(value interface{}) error { - switch d := value.(type) { - case string: - e.Set(d) - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return the CharField value -func (e *CharField) RawValue() interface{} { - return e.Value() -} +type CharField = models.CharField // verify CharField implement Fielder var _ Fielder = new(CharField) @@ -162,49 +82,7 @@ var _ Fielder = new(CharField) // Note that the current date is always used; it’s not just a default value that you can override. // // eg: `orm:"auto_now"` or `orm:"auto_now_add"` -type TimeField time.Time - -// Value return the time.Time -func (e TimeField) Value() time.Time { - return time.Time(e) -} - -// Set set the TimeField's value -func (e *TimeField) Set(d time.Time) { - *e = TimeField(d) -} - -// String convert time to string -func (e *TimeField) String() string { - return e.Value().String() -} - -// FieldType return enum type Date -func (e *TimeField) FieldType() int { - return TypeDateField -} - -// SetRaw convert the interface to time.Time. Allow string and time.Time -func (e *TimeField) SetRaw(value interface{}) error { - switch d := value.(type) { - case time.Time: - e.Set(d) - case string: - v, err := timeParse(d, formatTime) - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return time value -func (e *TimeField) RawValue() interface{} { - return e.Value() -} +type TimeField = models.TimeField var _ Fielder = new(TimeField) @@ -221,49 +99,7 @@ var _ Fielder = new(TimeField) // Note that the current date is always used; it’s not just a default value that you can override. // // eg: `orm:"auto_now"` or `orm:"auto_now_add"` -type DateField time.Time - -// Value return the time.Time -func (e DateField) Value() time.Time { - return time.Time(e) -} - -// Set set the DateField's value -func (e *DateField) Set(d time.Time) { - *e = DateField(d) -} - -// String convert datetime to string -func (e *DateField) String() string { - return e.Value().String() -} - -// FieldType return enum type Date -func (e *DateField) FieldType() int { - return TypeDateField -} - -// SetRaw convert the interface to time.Time. Allow string and time.Time -func (e *DateField) SetRaw(value interface{}) error { - switch d := value.(type) { - case time.Time: - e.Set(d) - case string: - v, err := timeParse(d, formatDate) - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return Date value -func (e *DateField) RawValue() interface{} { - return e.Value() -} +type DateField = models.DateField // verify DateField implement fielder interface var _ Fielder = new(DateField) @@ -271,513 +107,67 @@ var _ Fielder = new(DateField) // DateTimeField A date, represented in go by a time.Time instance. // datetime values like 2006-01-02 15:04:05 // Takes the same extra arguments as DateField. -type DateTimeField time.Time - -// Value return the datetime value -func (e DateTimeField) Value() time.Time { - return time.Time(e) -} - -// Set set the time.Time to datetime -func (e *DateTimeField) Set(d time.Time) { - *e = DateTimeField(d) -} - -// String return the time's String -func (e *DateTimeField) String() string { - return e.Value().String() -} - -// FieldType return the enum TypeDateTimeField -func (e *DateTimeField) FieldType() int { - return TypeDateTimeField -} - -// SetRaw convert the string or time.Time to DateTimeField -func (e *DateTimeField) SetRaw(value interface{}) error { - switch d := value.(type) { - case time.Time: - e.Set(d) - case string: - v, err := timeParse(d, formatDateTime) - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return the datetime value -func (e *DateTimeField) RawValue() interface{} { - return e.Value() -} +type DateTimeField = models.DateTimeField // verify datetime implement fielder -var _ Fielder = new(DateTimeField) +var _ models.Fielder = new(DateTimeField) // FloatField A floating-point number represented in go by a float32 value. -type FloatField float64 - -// Value return the FloatField value -func (e FloatField) Value() float64 { - return float64(e) -} - -// Set the Float64 -func (e *FloatField) Set(d float64) { - *e = FloatField(d) -} - -// String return the string -func (e *FloatField) String() string { - return ToStr(e.Value(), -1, 32) -} - -// FieldType return the enum type -func (e *FloatField) FieldType() int { - return TypeFloatField -} - -// SetRaw converter interface Float64 float32 or string to FloatField -func (e *FloatField) SetRaw(value interface{}) error { - switch d := value.(type) { - case float32: - e.Set(float64(d)) - case float64: - e.Set(d) - case string: - v, err := StrTo(d).Float64() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return the FloatField value -func (e *FloatField) RawValue() interface{} { - return e.Value() -} +type FloatField = models.FloatField // verify FloatField implement Fielder var _ Fielder = new(FloatField) // SmallIntegerField -32768 to 32767 -type SmallIntegerField int16 - -// Value return int16 value -func (e SmallIntegerField) Value() int16 { - return int16(e) -} - -// Set the SmallIntegerField value -func (e *SmallIntegerField) Set(d int16) { - *e = SmallIntegerField(d) -} - -// String convert smallint to string -func (e *SmallIntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return enum type SmallIntegerField -func (e *SmallIntegerField) FieldType() int { - return TypeSmallIntegerField -} - -// SetRaw convert interface int16/string to int16 -func (e *SmallIntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case int16: - e.Set(d) - case string: - v, err := StrTo(d).Int16() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return smallint value -func (e *SmallIntegerField) RawValue() interface{} { - return e.Value() -} +type SmallIntegerField = models.SmallIntegerField // verify SmallIntegerField implement Fielder var _ Fielder = new(SmallIntegerField) // IntegerField -2147483648 to 2147483647 -type IntegerField int32 - -// Value return the int32 -func (e IntegerField) Value() int32 { - return int32(e) -} - -// Set IntegerField value -func (e *IntegerField) Set(d int32) { - *e = IntegerField(d) -} - -// String convert Int32 to string -func (e *IntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return the enum type -func (e *IntegerField) FieldType() int { - return TypeIntegerField -} - -// SetRaw convert interface int32/string to int32 -func (e *IntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case int32: - e.Set(d) - case string: - v, err := StrTo(d).Int32() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return IntegerField value -func (e *IntegerField) RawValue() interface{} { - return e.Value() -} +type IntegerField = models.IntegerField // verify IntegerField implement Fielder var _ Fielder = new(IntegerField) // BigIntegerField -9223372036854775808 to 9223372036854775807. -type BigIntegerField int64 - -// Value return int64 -func (e BigIntegerField) Value() int64 { - return int64(e) -} - -// Set the BigIntegerField value -func (e *BigIntegerField) Set(d int64) { - *e = BigIntegerField(d) -} - -// String convert BigIntegerField to string -func (e *BigIntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return enum type -func (e *BigIntegerField) FieldType() int { - return TypeBigIntegerField -} - -// SetRaw convert interface int64/string to int64 -func (e *BigIntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case int64: - e.Set(d) - case string: - v, err := StrTo(d).Int64() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return BigIntegerField value -func (e *BigIntegerField) RawValue() interface{} { - return e.Value() -} +type BigIntegerField = models.BigIntegerField // verify BigIntegerField implement Fielder var _ Fielder = new(BigIntegerField) // PositiveSmallIntegerField 0 to 65535 -type PositiveSmallIntegerField uint16 - -// Value return uint16 -func (e PositiveSmallIntegerField) Value() uint16 { - return uint16(e) -} - -// Set PositiveSmallIntegerField value -func (e *PositiveSmallIntegerField) Set(d uint16) { - *e = PositiveSmallIntegerField(d) -} - -// String convert uint16 to string -func (e *PositiveSmallIntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return enum type -func (e *PositiveSmallIntegerField) FieldType() int { - return TypePositiveSmallIntegerField -} - -// SetRaw convert Interface uint16/string to uint16 -func (e *PositiveSmallIntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case uint16: - e.Set(d) - case string: - v, err := StrTo(d).Uint16() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue returns PositiveSmallIntegerField value -func (e *PositiveSmallIntegerField) RawValue() interface{} { - return e.Value() -} +type PositiveSmallIntegerField = models.PositiveSmallIntegerField // verify PositiveSmallIntegerField implement Fielder var _ Fielder = new(PositiveSmallIntegerField) // PositiveIntegerField 0 to 4294967295 -type PositiveIntegerField uint32 - -// Value return PositiveIntegerField value. Uint32 -func (e PositiveIntegerField) Value() uint32 { - return uint32(e) -} - -// Set the PositiveIntegerField value -func (e *PositiveIntegerField) Set(d uint32) { - *e = PositiveIntegerField(d) -} - -// String convert PositiveIntegerField to string -func (e *PositiveIntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return enum type -func (e *PositiveIntegerField) FieldType() int { - return TypePositiveIntegerField -} - -// SetRaw convert interface uint32/string to Uint32 -func (e *PositiveIntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case uint32: - e.Set(d) - case string: - v, err := StrTo(d).Uint32() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return the PositiveIntegerField Value -func (e *PositiveIntegerField) RawValue() interface{} { - return e.Value() -} +type PositiveIntegerField = models.PositiveIntegerField // verify PositiveIntegerField implement Fielder var _ Fielder = new(PositiveIntegerField) // PositiveBigIntegerField 0 to 18446744073709551615 -type PositiveBigIntegerField uint64 - -// Value return uint64 -func (e PositiveBigIntegerField) Value() uint64 { - return uint64(e) -} - -// Set PositiveBigIntegerField value -func (e *PositiveBigIntegerField) Set(d uint64) { - *e = PositiveBigIntegerField(d) -} - -// String convert PositiveBigIntegerField to string -func (e *PositiveBigIntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return enum type -func (e *PositiveBigIntegerField) FieldType() int { - return TypePositiveIntegerField -} - -// SetRaw convert interface uint64/string to Uint64 -func (e *PositiveBigIntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case uint64: - e.Set(d) - case string: - v, err := StrTo(d).Uint64() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return PositiveBigIntegerField value -func (e *PositiveBigIntegerField) RawValue() interface{} { - return e.Value() -} +type PositiveBigIntegerField = models.PositiveBigIntegerField // verify PositiveBigIntegerField implement Fielder var _ Fielder = new(PositiveBigIntegerField) // TextField A large text field. -type TextField string - -// Value return TextField value -func (e TextField) Value() string { - return string(e) -} - -// Set the TextField value -func (e *TextField) Set(d string) { - *e = TextField(d) -} - -// String convert TextField to string -func (e *TextField) String() string { - return e.Value() -} - -// FieldType return enum type -func (e *TextField) FieldType() int { - return TypeTextField -} - -// SetRaw convert interface string to string -func (e *TextField) SetRaw(value interface{}) error { - switch d := value.(type) { - case string: - e.Set(d) - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return TextField value -func (e *TextField) RawValue() interface{} { - return e.Value() -} +type TextField = models.TextField // verify TextField implement Fielder var _ Fielder = new(TextField) // JSONField postgres json field. -type JSONField string - -// Value return JSONField value -func (j JSONField) Value() string { - return string(j) -} - -// Set the JSONField value -func (j *JSONField) Set(d string) { - *j = JSONField(d) -} - -// String convert JSONField to string -func (j *JSONField) String() string { - return j.Value() -} - -// FieldType return enum type -func (j *JSONField) FieldType() int { - return TypeJSONField -} - -// SetRaw convert interface string to string -func (j *JSONField) SetRaw(value interface{}) error { - switch d := value.(type) { - case string: - j.Set(d) - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return JSONField value -func (j *JSONField) RawValue() interface{} { - return j.Value() -} +type JSONField = models.JSONField // verify JSONField implement Fielder -var _ Fielder = new(JSONField) +var _ models.Fielder = new(JSONField) // JsonbField postgres json field. -type JsonbField string - -// Value return JsonbField value -func (j JsonbField) Value() string { - return string(j) -} - -// Set the JsonbField value -func (j *JsonbField) Set(d string) { - *j = JsonbField(d) -} - -// String convert JsonbField to string -func (j *JsonbField) String() string { - return j.Value() -} - -// FieldType return enum type -func (j *JsonbField) FieldType() int { - return TypeJsonbField -} - -// SetRaw convert interface string to string -func (j *JsonbField) SetRaw(value interface{}) error { - switch d := value.(type) { - case string: - j.Set(d) - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return JsonbField value -func (j *JsonbField) RawValue() interface{} { - return j.Value() -} +type JsonbField = models.JsonbField // verify JsonbField implement Fielder -var _ Fielder = new(JsonbField) +var _ models.Fielder = new(JsonbField) diff --git a/client/orm/models_info_m.go b/client/orm/models_info_m.go deleted file mode 100644 index b94480ca..00000000 --- a/client/orm/models_info_m.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "fmt" - "os" - "reflect" -) - -// single model info -type modelInfo struct { - manual bool - isThrough bool - pkg string - name string - fullName string - table string - model interface{} - fields *fields - addrField reflect.Value // store the original struct value - uniques []string -} - -// new model info -func newModelInfo(val reflect.Value) (mi *modelInfo) { - mi = &modelInfo{} - mi.fields = newFields() - ind := reflect.Indirect(val) - mi.addrField = val - mi.name = ind.Type().Name() - mi.fullName = getFullName(ind.Type()) - addModelFields(mi, ind, "", []int{}) - return -} - -// index: FieldByIndex returns the nested field corresponding to index -func addModelFields(mi *modelInfo, ind reflect.Value, mName string, index []int) { - var ( - err error - fi *fieldInfo - sf reflect.StructField - ) - - for i := 0; i < ind.NumField(); i++ { - field := ind.Field(i) - sf = ind.Type().Field(i) - // if the field is unexported skip - if sf.PkgPath != "" { - continue - } - // add anonymous struct fields - if sf.Anonymous { - addModelFields(mi, field, mName+"."+sf.Name, append(index, i)) - continue - } - - fi, err = newFieldInfo(mi, field, sf, mName) - if err == errSkipField { - err = nil - continue - } else if err != nil { - break - } - // record current field index - fi.fieldIndex = append(fi.fieldIndex, index...) - fi.fieldIndex = append(fi.fieldIndex, i) - fi.mi = mi - fi.inModel = true - if !mi.fields.Add(fi) { - err = fmt.Errorf("duplicate column name: %s", fi.column) - break - } - if fi.pk { - if mi.fields.pk != nil { - err = fmt.Errorf("one model must have one pk field only") - break - } else { - mi.fields.pk = fi - } - } - } - - if err != nil { - fmt.Println(fmt.Errorf("field: %s.%s, %s", ind.Type(), sf.Name, err)) - os.Exit(2) - } -} - -// combine related model info to new model info. -// prepare for relation models query. -func newM2MModelInfo(m1, m2 *modelInfo) (mi *modelInfo) { - mi = new(modelInfo) - mi.fields = newFields() - mi.table = m1.table + "_" + m2.table + "s" - mi.name = camelString(mi.table) - mi.fullName = m1.pkg + "." + mi.name - - fa := new(fieldInfo) // pk - f1 := new(fieldInfo) // m1 table RelForeignKey - f2 := new(fieldInfo) // m2 table RelForeignKey - fa.fieldType = TypeBigIntegerField - fa.auto = true - fa.pk = true - fa.dbcol = true - fa.name = "Id" - fa.column = "id" - fa.fullName = mi.fullName + "." + fa.name - - f1.dbcol = true - f2.dbcol = true - f1.fieldType = RelForeignKey - f2.fieldType = RelForeignKey - f1.name = camelString(m1.table) - f2.name = camelString(m2.table) - f1.fullName = mi.fullName + "." + f1.name - f2.fullName = mi.fullName + "." + f2.name - f1.column = m1.table + "_id" - f2.column = m2.table + "_id" - f1.rel = true - f2.rel = true - f1.relTable = m1.table - f2.relTable = m2.table - f1.relModelInfo = m1 - f2.relModelInfo = m2 - f1.mi = mi - f2.mi = mi - - mi.fields.Add(fa) - mi.fields.Add(f1) - mi.fields.Add(f2) - mi.fields.pk = fa - - mi.uniques = []string{f1.column, f2.column} - return -} diff --git a/client/orm/models_test.go b/client/orm/models_test.go index ea8a89fc..52bafd9e 100644 --- a/client/orm/models_test.go +++ b/client/orm/models_test.go @@ -22,6 +22,8 @@ import ( "strings" "time" + "github.com/beego/beego/v2/client/orm/internal/models" + _ "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" _ "github.com/mattn/go-sqlite3" @@ -79,7 +81,7 @@ func (e *SliceStringField) RawValue() interface{} { return e.String() } -var _ Fielder = new(SliceStringField) +var _ models.Fielder = new(SliceStringField) // A json field. type JSONFieldTest struct { @@ -111,7 +113,7 @@ func (e *JSONFieldTest) RawValue() interface{} { return e.String() } -var _ Fielder = new(JSONFieldTest) +var _ models.Fielder = new(JSONFieldTest) type Data struct { ID int `orm:"column(id)"` diff --git a/client/orm/models_utils_test.go b/client/orm/models_utils_test.go deleted file mode 100644 index 4dceda1c..00000000 --- a/client/orm/models_utils_test.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package orm - -import ( - "reflect" - "testing" - - "github.com/stretchr/testify/assert" -) - -type NotApplicableModel struct { - Id int -} - -func (n *NotApplicableModel) IsApplicableTableForDB(db string) bool { - return db == "default" -} - -func TestIsApplicableTableForDB(t *testing.T) { - assert.False(t, isApplicableTableForDB(reflect.ValueOf(&NotApplicableModel{}), "defa")) - assert.True(t, isApplicableTableForDB(reflect.ValueOf(&NotApplicableModel{}), "default")) -} diff --git a/client/orm/orm.go b/client/orm/orm.go index 2c27a290..b7048409 100644 --- a/client/orm/orm.go +++ b/client/orm/orm.go @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build go1.8 -// +build go1.8 - // Package orm provide ORM for MySQL/PostgreSQL/sqlite // Simple Usage // @@ -50,7 +47,6 @@ // // delete // num, err = o.Delete(&u) // } -// package orm import ( @@ -58,9 +54,12 @@ import ( "database/sql" "errors" "fmt" - "os" "reflect" - "time" + + ilogs "github.com/beego/beego/v2/client/orm/internal/logs" + iutils "github.com/beego/beego/v2/client/orm/internal/utils" + + "github.com/beego/beego/v2/client/orm/internal/models" "github.com/beego/beego/v2/client/orm/clauses/order_clause" "github.com/beego/beego/v2/client/orm/hints" @@ -76,10 +75,10 @@ const ( // Define common vars var ( Debug = false - DebugLog = NewLog(os.Stdout) + DebugLog = ilogs.DebugLog DefaultRowsLimit = -1 DefaultRelsDepth = 2 - DefaultTimeLoc = time.Local + DefaultTimeLoc = iutils.DefaultTimeLoc ErrTxDone = errors.New(" transaction already done") ErrMultiRows = errors.New(" return multi rows") ErrNoRows = errors.New(" no row found") @@ -108,7 +107,7 @@ var ( ) // get model info and model reflect value -func (*ormBase) getMi(md interface{}) (mi *modelInfo) { +func (*ormBase) getMi(md interface{}) (mi *models.ModelInfo) { val := reflect.ValueOf(md) ind := reflect.Indirect(val) typ := ind.Type() @@ -117,19 +116,19 @@ func (*ormBase) getMi(md interface{}) (mi *modelInfo) { } // get need ptr model info and model reflect value -func (*ormBase) getPtrMiInd(md interface{}) (mi *modelInfo, ind reflect.Value) { +func (*ormBase) getPtrMiInd(md interface{}) (mi *models.ModelInfo, ind reflect.Value) { val := reflect.ValueOf(md) ind = reflect.Indirect(val) typ := ind.Type() if val.Kind() != reflect.Ptr { - panic(fmt.Errorf(" cannot use non-ptr model struct `%s`", getFullName(typ))) + panic(fmt.Errorf(" cannot use non-ptr model struct `%s`", models.GetFullName(typ))) } mi = getTypeMi(typ) return } -func getTypeMi(mdTyp reflect.Type) *modelInfo { - name := getFullName(mdTyp) +func getTypeMi(mdTyp reflect.Type) *models.ModelInfo { + name := models.GetFullName(mdTyp) if mi, ok := defaultModelCache.getByFullName(name); ok { return mi } @@ -137,10 +136,10 @@ func getTypeMi(mdTyp reflect.Type) *modelInfo { } // get field info from model info by given field name -func (*ormBase) getFieldInfo(mi *modelInfo, name string) *fieldInfo { - fi, ok := mi.fields.GetByAny(name) +func (*ormBase) getFieldInfo(mi *models.ModelInfo, name string) *models.FieldInfo { + fi, ok := mi.Fields.GetByAny(name) if !ok { - panic(fmt.Errorf(" cannot find field `%s` for model `%s`", name, mi.fullName)) + panic(fmt.Errorf(" cannot find field `%s` for model `%s`", name, mi.FullName)) } return fi } @@ -180,11 +179,11 @@ func (o *ormBase) ReadOrCreateWithCtx(ctx context.Context, md interface{}, col1 return err == nil, id, err } - id, vid := int64(0), ind.FieldByIndex(mi.fields.pk.fieldIndex) - if mi.fields.pk.fieldType&IsPositiveIntegerField > 0 { + id, vid := int64(0), ind.FieldByIndex(mi.Fields.Pk.FieldIndex) + if mi.Fields.Pk.FieldType&IsPositiveIntegerField > 0 { id = int64(vid.Uint()) - } else if mi.fields.pk.rel { - return o.ReadOrCreateWithCtx(ctx, vid.Interface(), mi.fields.pk.relModelInfo.fields.pk.name) + } else if mi.Fields.Pk.Rel { + return o.ReadOrCreateWithCtx(ctx, vid.Interface(), mi.Fields.Pk.RelModelInfo.Fields.Pk.Name) } else { id = vid.Int() } @@ -210,12 +209,12 @@ func (o *ormBase) InsertWithCtx(ctx context.Context, md interface{}) (int64, err } // set auto pk field -func (*ormBase) setPk(mi *modelInfo, ind reflect.Value, id int64) { - if mi.fields.pk.auto { - if mi.fields.pk.fieldType&IsPositiveIntegerField > 0 { - ind.FieldByIndex(mi.fields.pk.fieldIndex).SetUint(uint64(id)) +func (*ormBase) setPk(mi *models.ModelInfo, ind reflect.Value, id int64) { + if mi.Fields.Pk != nil && mi.Fields.Pk.Auto { + if mi.Fields.Pk.FieldType&IsPositiveIntegerField > 0 { + ind.FieldByIndex(mi.Fields.Pk.FieldIndex).SetUint(uint64(id)) } else { - ind.FieldByIndex(mi.fields.pk.fieldIndex).SetInt(id) + ind.FieldByIndex(mi.Fields.Pk.FieldIndex).SetInt(id) } } } @@ -277,7 +276,7 @@ func (o *ormBase) InsertOrUpdateWithCtx(ctx context.Context, md interface{}, col } // update model to database. -// cols set the columns those want to update. +// cols set the Columns those want to update. func (o *ormBase) Update(md interface{}, cols ...string) (int64, error) { return o.UpdateWithCtx(context.Background(), md, cols...) } @@ -305,10 +304,10 @@ func (o *ormBase) QueryM2M(md interface{}, name string) QueryM2Mer { fi := o.getFieldInfo(mi, name) switch { - case fi.fieldType == RelManyToMany: - case fi.fieldType == RelReverseMany && fi.reverseFieldInfo.mi.isThrough: + case fi.FieldType == RelManyToMany: + case fi.FieldType == RelReverseMany && fi.ReverseFieldInfo.Mi.IsThrough: default: - panic(fmt.Errorf(" model `%s` . name `%s` is not a m2m field", fi.name, mi.fullName)) + panic(fmt.Errorf(" model `%s` . name `%s` is not a m2m field", fi.Name, mi.FullName)) } return newQueryM2M(md, o, mi, fi, ind) @@ -324,8 +323,9 @@ func (o *ormBase) QueryM2MWithCtx(_ context.Context, md interface{}, name string // args are limit, offset int and order string. // // example: -// orm.LoadRelated(post,"Tags") -// for _,tag := range post.Tags{...} +// +// orm.LoadRelated(post,"Tags") +// for _,tag := range post.Tags{...} // // make sure the relation is defined in model struct tags. func (o *ormBase) LoadRelated(md interface{}, name string, args ...utils.KV) (int64, error) { @@ -362,7 +362,7 @@ func (o *ormBase) LoadRelatedWithCtx(_ context.Context, md interface{}, name str } }) - switch fi.fieldType { + switch fi.FieldType { case RelOneToOne, RelForeignKey, RelReverseOne: limit = 1 offset = 0 @@ -376,11 +376,11 @@ func (o *ormBase) LoadRelatedWithCtx(_ context.Context, md interface{}, name str qs.orders = order_clause.ParseOrder(order) } - find := ind.FieldByIndex(fi.fieldIndex) + find := ind.FieldByIndex(fi.FieldIndex) var nums int64 var err error - switch fi.fieldType { + switch fi.FieldType { case RelOneToOne, RelForeignKey, RelReverseOne: val := reflect.New(find.Type().Elem()) container := val.Interface() @@ -397,7 +397,7 @@ func (o *ormBase) LoadRelatedWithCtx(_ context.Context, md interface{}, name str } // get QuerySeter for related models to md model -func (o *ormBase) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, reflect.Value, *querySet) { +func (o *ormBase) queryRelated(md interface{}, name string) (*models.ModelInfo, *models.FieldInfo, reflect.Value, *querySet) { mi, ind := o.getPtrMiInd(md) fi := o.getFieldInfo(mi, name) @@ -408,14 +408,14 @@ func (o *ormBase) queryRelated(md interface{}, name string) (*modelInfo, *fieldI var qs *querySet - switch fi.fieldType { + switch fi.FieldType { case RelOneToOne, RelForeignKey, RelManyToMany: - if !fi.inModel { + if !fi.InModel { break } qs = o.getRelQs(md, mi, fi) case RelReverseOne, RelReverseMany: - if !fi.inModel { + if !fi.InModel { break } qs = o.getReverseQs(md, mi, fi) @@ -429,41 +429,41 @@ func (o *ormBase) queryRelated(md interface{}, name string) (*modelInfo, *fieldI } // get reverse relation QuerySeter -func (o *ormBase) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { - switch fi.fieldType { +func (o *ormBase) getReverseQs(md interface{}, mi *models.ModelInfo, fi *models.FieldInfo) *querySet { + switch fi.FieldType { case RelReverseOne, RelReverseMany: default: - panic(fmt.Errorf(" name `%s` for model `%s` is not an available reverse field", fi.name, mi.fullName)) + panic(fmt.Errorf(" name `%s` for model `%s` is not an available reverse field", fi.Name, mi.FullName)) } var q *querySet - if fi.fieldType == RelReverseMany && fi.reverseFieldInfo.mi.isThrough { - q = newQuerySet(o, fi.relModelInfo).(*querySet) - q.cond = NewCondition().And(fi.reverseFieldInfoM2M.column+ExprSep+fi.reverseFieldInfo.column, md) + if fi.FieldType == RelReverseMany && fi.ReverseFieldInfo.Mi.IsThrough { + q = newQuerySet(o, fi.RelModelInfo).(*querySet) + q.cond = NewCondition().And(fi.ReverseFieldInfoM2M.Column+ExprSep+fi.ReverseFieldInfo.Column, md) } else { - q = newQuerySet(o, fi.reverseFieldInfo.mi).(*querySet) - q.cond = NewCondition().And(fi.reverseFieldInfo.column, md) + q = newQuerySet(o, fi.ReverseFieldInfo.Mi).(*querySet) + q.cond = NewCondition().And(fi.ReverseFieldInfo.Column, md) } return q } // get relation QuerySeter -func (o *ormBase) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { - switch fi.fieldType { +func (o *ormBase) getRelQs(md interface{}, mi *models.ModelInfo, fi *models.FieldInfo) *querySet { + switch fi.FieldType { case RelOneToOne, RelForeignKey, RelManyToMany: default: - panic(fmt.Errorf(" name `%s` for model `%s` is not an available rel field", fi.name, mi.fullName)) + panic(fmt.Errorf(" name `%s` for model `%s` is not an available rel field", fi.Name, mi.FullName)) } - q := newQuerySet(o, fi.relModelInfo).(*querySet) + q := newQuerySet(o, fi.RelModelInfo).(*querySet) q.cond = NewCondition() - if fi.fieldType == RelManyToMany { - q.cond = q.cond.And(fi.reverseFieldInfoM2M.column+ExprSep+fi.reverseFieldInfo.column, md) + if fi.FieldType == RelManyToMany { + q.cond = q.cond.And(fi.ReverseFieldInfoM2M.Column+ExprSep+fi.ReverseFieldInfo.Column, md) } else { - q.cond = q.cond.And(fi.reverseFieldInfo.column, md) + q.cond = q.cond.And(fi.ReverseFieldInfo.Column, md) } return q @@ -475,12 +475,12 @@ func (o *ormBase) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *queryS func (o *ormBase) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { var name string if table, ok := ptrStructOrTableName.(string); ok { - name = nameStrategyMap[defaultNameStrategy](table) + name = models.NameStrategyMap[models.DefaultNameStrategy](table) if mi, ok := defaultModelCache.get(name); ok { qs = newQuerySet(o, mi) } } else { - name = getFullName(indirectType(reflect.TypeOf(ptrStructOrTableName))) + name = models.GetFullName(iutils.IndirectType(reflect.TypeOf(ptrStructOrTableName))) if mi, ok := defaultModelCache.getByFullName(name); ok { qs = newQuerySet(o, mi) } diff --git a/client/orm/orm_log.go b/client/orm/orm_log.go index e6f8bc83..50ebc3a6 100644 --- a/client/orm/orm_log.go +++ b/client/orm/orm_log.go @@ -22,23 +22,22 @@ import ( "log" "strings" "time" + + "github.com/beego/beego/v2/client/orm/internal/logs" ) -// Log implement the log.Logger -type Log struct { - *log.Logger -} - -// costomer log func -var LogFunc func(query map[string]interface{}) +type Log = logs.Log // NewLog set io.Writer to create a Logger. -func NewLog(out io.Writer) *Log { - d := new(Log) +func NewLog(out io.Writer) *logs.Log { + d := new(logs.Log) d.Logger = log.New(out, "[ORM]", log.LstdFlags) return d } +// LogFunc costomer log func +var LogFunc func(query map[string]interface{}) + func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error, args ...interface{}) { logMap := make(map[string]interface{}) sub := time.Since(t) / 1e5 @@ -64,7 +63,7 @@ func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error if LogFunc != nil { LogFunc(logMap) } - DebugLog.Println(con) + logs.DebugLog.Println(con) } // statement query logger struct. diff --git a/client/orm/orm_object.go b/client/orm/orm_object.go index 50c1ca41..55395fe5 100644 --- a/client/orm/orm_object.go +++ b/client/orm/orm_object.go @@ -18,11 +18,13 @@ import ( "context" "fmt" "reflect" + + "github.com/beego/beego/v2/client/orm/internal/models" ) // an insert queryer struct type insertSet struct { - mi *modelInfo + mi *models.ModelInfo orm *ormBase stmt stmtQuerier closed bool @@ -42,23 +44,23 @@ func (o *insertSet) InsertWithCtx(ctx context.Context, md interface{}) (int64, e val := reflect.ValueOf(md) ind := reflect.Indirect(val) typ := ind.Type() - name := getFullName(typ) + name := models.GetFullName(typ) if val.Kind() != reflect.Ptr { panic(fmt.Errorf(" cannot use non-ptr model struct `%s`", name)) } - if name != o.mi.fullName { - panic(fmt.Errorf(" need model `%s` but found `%s`", o.mi.fullName, name)) + if name != o.mi.FullName { + panic(fmt.Errorf(" need model `%s` but found `%s`", o.mi.FullName, name)) } id, err := o.orm.alias.DbBaser.InsertStmt(ctx, o.stmt, o.mi, ind, o.orm.alias.TZ) if err != nil { return id, err } if id > 0 { - if o.mi.fields.pk.auto { - if o.mi.fields.pk.fieldType&IsPositiveIntegerField > 0 { - ind.FieldByIndex(o.mi.fields.pk.fieldIndex).SetUint(uint64(id)) + if o.mi.Fields.Pk.Auto { + if o.mi.Fields.Pk.FieldType&IsPositiveIntegerField > 0 { + ind.FieldByIndex(o.mi.Fields.Pk.FieldIndex).SetUint(uint64(id)) } else { - ind.FieldByIndex(o.mi.fields.pk.fieldIndex).SetInt(id) + ind.FieldByIndex(o.mi.Fields.Pk.FieldIndex).SetInt(id) } } } @@ -75,7 +77,7 @@ func (o *insertSet) Close() error { } // create new insert queryer. -func newInsertSet(ctx context.Context, orm *ormBase, mi *modelInfo) (Inserter, error) { +func newInsertSet(ctx context.Context, orm *ormBase, mi *models.ModelInfo) (Inserter, error) { bi := new(insertSet) bi.orm = orm bi.mi = mi diff --git a/client/orm/orm_querym2m.go b/client/orm/orm_querym2m.go index 9da49bba..6dc66b3d 100644 --- a/client/orm/orm_querym2m.go +++ b/client/orm/orm_querym2m.go @@ -17,22 +17,25 @@ package orm import ( "context" "reflect" + + "github.com/beego/beego/v2/client/orm/internal/models" ) // model to model struct type queryM2M struct { md interface{} - mi *modelInfo - fi *fieldInfo + mi *models.ModelInfo + fi *models.FieldInfo qs *querySet ind reflect.Value } // add models to origin models when creating queryM2M. // example: -// m2m := orm.QueryM2M(post,"Tag") -// m2m.Add(&Tag1{},&Tag2{}) -// for _,tag := range post.Tags{} +// +// m2m := orm.QueryM2M(post,"Tag") +// m2m.Add(&Tag1{},&Tag2{}) +// for _,tag := range post.Tags{} // // make sure the relation is defined in post model struct tag. func (o *queryM2M) Add(mds ...interface{}) (int64, error) { @@ -41,9 +44,9 @@ func (o *queryM2M) Add(mds ...interface{}) (int64, error) { func (o *queryM2M) AddWithCtx(ctx context.Context, mds ...interface{}) (int64, error) { fi := o.fi - mi := fi.relThroughModelInfo - mfi := fi.reverseFieldInfo - rfi := fi.reverseFieldInfoTwo + mi := fi.RelThroughModelInfo + mfi := fi.ReverseFieldInfo + rfi := fi.ReverseFieldInfoTwo orm := o.qs.orm dbase := orm.alias.DbBaser @@ -52,9 +55,9 @@ func (o *queryM2M) AddWithCtx(ctx context.Context, mds ...interface{}) (int64, e var otherValues []interface{} var otherNames []string - for _, colname := range mi.fields.dbcols { - if colname != mfi.column && colname != rfi.column && colname != fi.mi.fields.pk.column && - mi.fields.columns[colname] != mi.fields.pk { + for _, colname := range mi.Fields.DBcols { + if colname != mfi.Column && colname != rfi.Column && colname != fi.Mi.Fields.Pk.Column && + mi.Fields.Columns[colname] != mi.Fields.Pk { otherNames = append(otherNames, colname) } } @@ -83,7 +86,7 @@ func (o *queryM2M) AddWithCtx(ctx context.Context, mds ...interface{}) (int64, e panic(ErrMissPK) } - names := []string{mfi.column, rfi.column} + names := []string{mfi.Column, rfi.Column} values := make([]interface{}, 0, len(models)*2) for _, md := range models { @@ -93,7 +96,7 @@ func (o *queryM2M) AddWithCtx(ctx context.Context, mds ...interface{}) (int64, e if ind.Kind() != reflect.Struct { v2 = ind.Interface() } else { - _, v2, exist = getExistPk(fi.relModelInfo, ind) + _, v2, exist = getExistPk(fi.RelModelInfo, ind) if !exist { panic(ErrMissPK) } @@ -113,9 +116,9 @@ func (o *queryM2M) Remove(mds ...interface{}) (int64, error) { func (o *queryM2M) RemoveWithCtx(ctx context.Context, mds ...interface{}) (int64, error) { fi := o.fi - qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md) + qs := o.qs.Filter(fi.ReverseFieldInfo.Name, o.md) - return qs.Filter(fi.reverseFieldInfoTwo.name+ExprSep+"in", mds).Delete() + return qs.Filter(fi.ReverseFieldInfoTwo.Name+ExprSep+"in", mds).Delete() } // check model is existed in relationship of origin model @@ -125,8 +128,8 @@ func (o *queryM2M) Exist(md interface{}) bool { func (o *queryM2M) ExistWithCtx(ctx context.Context, md interface{}) bool { fi := o.fi - return o.qs.Filter(fi.reverseFieldInfo.name, o.md). - Filter(fi.reverseFieldInfoTwo.name, md).ExistWithCtx(ctx) + return o.qs.Filter(fi.ReverseFieldInfo.Name, o.md). + Filter(fi.ReverseFieldInfoTwo.Name, md).ExistWithCtx(ctx) } // clean all models in related of origin model @@ -136,7 +139,7 @@ func (o *queryM2M) Clear() (int64, error) { func (o *queryM2M) ClearWithCtx(ctx context.Context) (int64, error) { fi := o.fi - return o.qs.Filter(fi.reverseFieldInfo.name, o.md).DeleteWithCtx(ctx) + return o.qs.Filter(fi.ReverseFieldInfo.Name, o.md).DeleteWithCtx(ctx) } // count all related models of origin model @@ -146,18 +149,18 @@ func (o *queryM2M) Count() (int64, error) { func (o *queryM2M) CountWithCtx(ctx context.Context) (int64, error) { fi := o.fi - return o.qs.Filter(fi.reverseFieldInfo.name, o.md).CountWithCtx(ctx) + return o.qs.Filter(fi.ReverseFieldInfo.Name, o.md).CountWithCtx(ctx) } var _ QueryM2Mer = new(queryM2M) // create new M2M queryer. -func newQueryM2M(md interface{}, o *ormBase, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer { +func newQueryM2M(md interface{}, o *ormBase, mi *models.ModelInfo, fi *models.FieldInfo, ind reflect.Value) QueryM2Mer { qm2m := new(queryM2M) qm2m.md = md qm2m.mi = mi qm2m.fi = fi qm2m.ind = ind - qm2m.qs = newQuerySet(o, fi.relThroughModelInfo).(*querySet) + qm2m.qs = newQuerySet(o, fi.RelThroughModelInfo).(*querySet) return qm2m } diff --git a/client/orm/orm_queryset.go b/client/orm/orm_queryset.go index 82325899..8464741b 100644 --- a/client/orm/orm_queryset.go +++ b/client/orm/orm_queryset.go @@ -18,6 +18,10 @@ import ( "context" "fmt" + "github.com/beego/beego/v2/client/orm/internal/utils" + + "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/beego/beego/v2/client/orm/clauses/order_clause" "github.com/beego/beego/v2/client/orm/hints" ) @@ -43,9 +47,10 @@ const ( ) // ColValue do the field raw changes. e.g Nums = Nums + 10. usage: -// Params{ -// "Nums": ColValue(Col_Add, 10), -// } +// +// Params{ +// "Nums": ColValue(Col_Add, 10), +// } func ColValue(opt operator, value interface{}) interface{} { switch opt { case ColAdd, ColMinus, ColMultiply, ColExcept, ColBitAnd, ColBitRShift, @@ -53,7 +58,7 @@ func ColValue(opt operator, value interface{}) interface{} { default: panic(fmt.Errorf("orm.ColValue wrong operator")) } - v, err := StrTo(ToStr(value)).Int64() + v, err := utils.StrTo(utils.ToStr(value)).Int64() if err != nil { panic(fmt.Errorf("orm.ColValue doesn't support non string/numeric type, %s", err)) } @@ -65,7 +70,7 @@ func ColValue(opt operator, value interface{}) interface{} { // real query struct type querySet struct { - mi *modelInfo + mi *models.ModelInfo cond *Condition related []string relDepth int @@ -112,13 +117,13 @@ func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { // set offset number func (o *querySet) setOffset(num interface{}) { - o.offset = ToInt64(num) + o.offset = utils.ToInt64(num) } // add LIMIT value. // args[0] means offset, e.g. LIMIT num,offset. func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter { - o.limit = ToInt64(limit) + o.limit = utils.ToInt64(limit) if len(args) > 0 { o.setOffset(args[0]) } @@ -260,8 +265,9 @@ func (o *querySet) DeleteWithCtx(ctx context.Context) (int64, error) { // return an insert queryer. // it can be used in times. // example: -// i,err := sq.PrepareInsert() -// i.Add(&user1{},&user2{}) +// +// i,err := sq.PrepareInsert() +// i.Add(&user1{},&user2{}) func (o *querySet) PrepareInsert() (Inserter, error) { return o.PrepareInsertWithCtx(context.Background()) } @@ -271,7 +277,7 @@ func (o *querySet) PrepareInsertWithCtx(ctx context.Context) (Inserter, error) { } // query all data and map to containers. -// cols means the columns when querying. +// cols means the Columns when querying. func (o *querySet) All(container interface{}, cols ...string) (int64, error) { return o.AllWithCtx(context.Background(), container, cols...) } @@ -281,7 +287,7 @@ func (o *querySet) AllWithCtx(ctx context.Context, container interface{}, cols . } // query one row data and map to containers. -// cols means the columns when querying. +// cols means the Columns when querying. func (o *querySet) One(container interface{}, cols ...string) error { return o.OneWithCtx(context.Background(), container, cols...) } @@ -339,10 +345,11 @@ func (o *querySet) ValuesFlatWithCtx(ctx context.Context, result *ParamsList, ex // name | value // total | 100 // found | 200 -// to map[string]interface{}{ -// "total": 100, -// "found": 200, -// } +// +// to map[string]interface{}{ +// "total": 100, +// "found": 200, +// } func (o *querySet) RowsToMap(result *Params, keyCol, valueCol string) (int64, error) { panic(ErrNotImplement) } @@ -353,16 +360,17 @@ func (o *querySet) RowsToMap(result *Params, keyCol, valueCol string) (int64, er // name | value // total | 100 // found | 200 -// to struct { -// Total int -// Found int -// } +// +// to struct { +// Total int +// Found int +// } func (o *querySet) RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error) { panic(ErrNotImplement) } // create new QuerySeter. -func newQuerySet(orm *ormBase, mi *modelInfo) QuerySeter { +func newQuerySet(orm *ormBase, mi *models.ModelInfo) QuerySeter { o := new(querySet) o.mi = mi o.orm = orm diff --git a/client/orm/orm_raw.go b/client/orm/orm_raw.go index f4f3a62e..2f811c65 100644 --- a/client/orm/orm_raw.go +++ b/client/orm/orm_raw.go @@ -20,6 +20,10 @@ import ( "reflect" "time" + "github.com/beego/beego/v2/client/orm/internal/utils" + + "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/pkg/errors" ) @@ -95,7 +99,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { } else if v, ok := value.(bool); ok { ind.SetBool(v) } else { - v, _ := StrTo(ToStr(value)).Bool() + v, _ := utils.StrTo(utils.ToStr(value)).Bool() ind.SetBool(v) } @@ -103,7 +107,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { if value == nil { ind.SetString("") } else { - ind.SetString(ToStr(value)) + ind.SetString(utils.ToStr(value)) } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: @@ -117,7 +121,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: ind.SetInt(int64(val.Uint())) default: - v, _ := StrTo(ToStr(value)).Int64() + v, _ := utils.StrTo(utils.ToStr(value)).Int64() ind.SetInt(v) } } @@ -132,7 +136,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: ind.SetUint(val.Uint()) default: - v, _ := StrTo(ToStr(value)).Uint64() + v, _ := utils.StrTo(utils.ToStr(value)).Uint64() ind.SetUint(v) } } @@ -145,7 +149,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { case reflect.Float64: ind.SetFloat(val.Float()) default: - v, _ := StrTo(ToStr(value)).Float64() + v, _ := utils.StrTo(utils.ToStr(value)).Float64() ind.SetFloat(v) } } @@ -170,20 +174,20 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { if str != "" { if len(str) >= 19 { str = str[:19] - t, err := time.ParseInLocation(formatDateTime, str, o.orm.alias.TZ) + t, err := time.ParseInLocation(utils.FormatDateTime, str, o.orm.alias.TZ) if err == nil { t = t.In(DefaultTimeLoc) ind.Set(reflect.ValueOf(t)) } } else if len(str) >= 10 { str = str[:10] - t, err := time.ParseInLocation(formatDate, str, DefaultTimeLoc) + t, err := time.ParseInLocation(utils.FormatDate, str, DefaultTimeLoc) if err == nil { ind.Set(reflect.ValueOf(t)) } } else if len(str) >= 8 { str = str[:8] - t, err := time.ParseInLocation(formatTime, str, DefaultTimeLoc) + t, err := time.ParseInLocation(utils.FormatTime, str, DefaultTimeLoc) if err == nil { ind.Set(reflect.ValueOf(t)) } @@ -287,7 +291,7 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { refs = make([]interface{}, 0, len(containers)) sInds []reflect.Value eTyps []reflect.Type - sMi *modelInfo + sMi *models.ModelInfo ) structMode := false for _, container := range containers { @@ -313,7 +317,7 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { } structMode = true - fn := getFullName(typ) + fn := models.GetFullName(typ) if mi, ok := defaultModelCache.getByFullName(fn); ok { sMi = mi } @@ -370,16 +374,16 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { if sMi != nil { for _, col := range columns { - if fi := sMi.fields.GetByColumn(col); fi != nil { + if fi := sMi.Fields.GetByColumn(col); fi != nil { value := reflect.ValueOf(columnsMp[col]).Elem().Interface() - field := ind.FieldByIndex(fi.fieldIndex) - if fi.fieldType&IsRelField > 0 { - mf := reflect.New(fi.relModelInfo.addrField.Elem().Type()) + field := ind.FieldByIndex(fi.FieldIndex) + if fi.FieldType&IsRelField > 0 { + mf := reflect.New(fi.RelModelInfo.AddrField.Elem().Type()) field.Set(mf) - field = mf.Elem().FieldByIndex(fi.relModelInfo.fields.pk.fieldIndex) + field = mf.Elem().FieldByIndex(fi.RelModelInfo.Fields.Pk.FieldIndex) } - if fi.isFielder { - fd := field.Addr().Interface().(Fielder) + if fi.IsFielder { + fd := field.Addr().Interface().(models.Fielder) err := fd.SetRaw(value) if err != nil { return errors.Errorf("set raw error:%s", err) @@ -406,12 +410,12 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { // thanks @Gazeboxu. tags := structTagMap[fe.Tag] if tags == nil { - _, tags = parseStructTag(fe.Tag.Get(defaultStructTagName)) + _, tags = models.ParseStructTag(fe.Tag.Get(models.DefaultStructTagName)) structTagMap[fe.Tag] = tags } var col string if col = tags["column"]; col == "" { - col = nameStrategyMap[nameStrategy](fe.Name) + col = models.NameStrategyMap[models.NameStrategy](fe.Name) } if v, ok := columnsMp[col]; ok { value := reflect.ValueOf(v).Elem().Interface() @@ -443,13 +447,13 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { return nil } -// query data rows and map to container +// QueryRows query data rows and map to container func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { var ( refs = make([]interface{}, 0, len(containers)) sInds []reflect.Value eTyps []reflect.Type - sMi *modelInfo + sMi *models.ModelInfo ) structMode := false for _, container := range containers { @@ -474,7 +478,7 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { } structMode = true - fn := getFullName(typ) + fn := models.GetFullName(typ) if mi, ok := defaultModelCache.getByFullName(fn); ok { sMi = mi } @@ -500,7 +504,6 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { sInd := sInds[0] for rows.Next() { - if structMode { columns, err := rows.Columns() if err != nil { @@ -537,16 +540,16 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { if sMi != nil { for _, col := range columns { - if fi := sMi.fields.GetByColumn(col); fi != nil { + if fi := sMi.Fields.GetByColumn(col); fi != nil { value := reflect.ValueOf(columnsMp[col]).Elem().Interface() - field := ind.FieldByIndex(fi.fieldIndex) - if fi.fieldType&IsRelField > 0 { - mf := reflect.New(fi.relModelInfo.addrField.Elem().Type()) + field := ind.FieldByIndex(fi.FieldIndex) + if fi.FieldType&IsRelField > 0 { + mf := reflect.New(fi.RelModelInfo.AddrField.Elem().Type()) field.Set(mf) - field = mf.Elem().FieldByIndex(fi.relModelInfo.fields.pk.fieldIndex) + field = mf.Elem().FieldByIndex(fi.RelModelInfo.Fields.Pk.FieldIndex) } - if fi.isFielder { - fd := field.Addr().Interface().(Fielder) + if fi.IsFielder { + fd := field.Addr().Interface().(models.Fielder) err := fd.SetRaw(value) if err != nil { return 0, errors.Errorf("set raw error:%s", err) @@ -570,10 +573,10 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { recursiveSetField(f) } - _, tags := parseStructTag(fe.Tag.Get(defaultStructTagName)) + _, tags := models.ParseStructTag(fe.Tag.Get(models.DefaultStructTagName)) var col string if col = tags["column"]; col == "" { - col = nameStrategyMap[nameStrategy](fe.Name) + col = models.NameStrategyMap[models.NameStrategy](fe.Name) } if v, ok := columnsMp[col]; ok { value := reflect.ValueOf(v).Elem().Interface() @@ -593,16 +596,18 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { sInd = reflect.Append(sInd, ind) } else { - if err := rows.Scan(refs...); err != nil { + if err = rows.Scan(refs...); err != nil { return 0, err } - o.loopSetRefs(refs, sInds, &nInds, eTyps, cnt == 0) } - cnt++ } + if err = rows.Err(); err != nil { + return 0, err + } + if cnt > 0 { if structMode { sInds[0].Set(sInd) @@ -730,6 +735,10 @@ func (o *rawSet) readValues(container interface{}, needCols []string) (int64, er cnt++ } + if err = rs.Err(); err != nil { + return 0, err + } + switch v := container.(type) { case *[]Params: *v = maps @@ -837,7 +846,7 @@ func (o *rawSet) queryRowsTo(container interface{}, keyCol, valueCol string) (in } default: - if id := ind.FieldByName(camelString(key)); id.IsValid() { + if id := ind.FieldByName(models.CamelString(key)); id.IsValid() { o.setFieldValue(id, reflect.ValueOf(refs[valueIndex]).Elem().Interface()) } } @@ -845,6 +854,9 @@ func (o *rawSet) queryRowsTo(container interface{}, keyCol, valueCol string) (in cnt++ } + if err = rs.Err(); err != nil { + return 0, err + } if typ == 1 { v, _ := container.(*Params) *v = maps @@ -874,10 +886,11 @@ func (o *rawSet) ValuesFlat(container *ParamsList, cols ...string) (int64, error // name | value // total | 100 // found | 200 -// to map[string]interface{}{ -// "total": 100, -// "found": 200, -// } +// +// to map[string]interface{}{ +// "total": 100, +// "found": 200, +// } func (o *rawSet) RowsToMap(result *Params, keyCol, valueCol string) (int64, error) { return o.queryRowsTo(result, keyCol, valueCol) } @@ -888,10 +901,11 @@ func (o *rawSet) RowsToMap(result *Params, keyCol, valueCol string) (int64, erro // name | value // total | 100 // found | 200 -// to struct { -// Total int -// Found int -// } +// +// to struct { +// Total int +// Found int +// } func (o *rawSet) RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error) { return o.queryRowsTo(ptrStruct, keyCol, valueCol) } diff --git a/client/orm/orm_test.go b/client/orm/orm_test.go index 4fbd3a20..526e53e6 100644 --- a/client/orm/orm_test.go +++ b/client/orm/orm_test.go @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build go1.8 -// +build go1.8 - package orm import ( @@ -22,7 +19,6 @@ import ( "context" "database/sql" "fmt" - "io/ioutil" "math" "os" "path/filepath" @@ -32,6 +28,12 @@ import ( "testing" "time" + "github.com/beego/beego/v2/client/orm/internal/logs" + + "github.com/beego/beego/v2/client/orm/internal/utils" + + "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/stretchr/testify/assert" "github.com/beego/beego/v2/client/orm/clauses/order_clause" @@ -41,9 +43,9 @@ import ( var _ = os.PathSeparator var ( - testDate = formatDate + " -0700" - testDateTime = formatDateTime + " -0700" - testTime = formatTime + " -0700" + testDate = utils.FormatDate + " -0700" + testDateTime = utils.FormatDateTime + " -0700" + testTime = utils.FormatTime + " -0700" ) type argAny []interface{} @@ -72,7 +74,7 @@ func ValuesCompare(is bool, a interface{}, args ...interface{}) (ok bool, err er case time.Time: if v2, vo := b.(time.Time); vo { if arg.Get(1) != nil { - format := ToStr(arg.Get(1)) + format := utils.ToStr(arg.Get(1)) a = v.Format(format) b = v2.Format(format) ok = a == b @@ -82,7 +84,7 @@ func ValuesCompare(is bool, a interface{}, args ...interface{}) (ok bool, err er } } default: - ok = ToStr(a) == ToStr(b) + ok = utils.ToStr(a) == utils.ToStr(b) } ok = is && ok || !is && !ok if !ok { @@ -115,7 +117,7 @@ func getCaller(skip int) string { pc, file, line, _ := runtime.Caller(skip) fun := runtime.FuncForPC(pc) _, fn := filepath.Split(file) - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) var codes []string if err == nil { lines := bytes.Split(data, []byte{'\n'}) @@ -250,14 +252,14 @@ func TestRegisterModels(_ *testing.T) { func TestModelSyntax(t *testing.T) { user := &User{} ind := reflect.ValueOf(user).Elem() - fn := getFullName(ind.Type()) + fn := models.GetFullName(ind.Type()) _, ok := defaultModelCache.getByFullName(fn) throwFail(t, AssertIs(ok, true)) mi, ok := defaultModelCache.get("user") throwFail(t, AssertIs(ok, true)) if ok { - throwFail(t, AssertIs(mi.fields.GetByName("ShouldSkip") == nil, true)) + throwFail(t, AssertIs(mi.Fields.GetByName("ShouldSkip") == nil, true)) } } @@ -561,7 +563,7 @@ func TestNullDataTypes(t *testing.T) { assert.True(t, (*d.DatePtr).UTC().Sub(datePtr.UTC()) <= time.Second) assert.True(t, (*d.DateTimePtr).UTC().Sub(dateTimePtr.UTC()) <= time.Second) - // test support for pointer fields using RawSeter.QueryRows() + // test support for pointer Fields using RawSeter.QueryRows() var dnList []*DataNull Q := dDbBaser.TableQuote() num, err = dORM.Raw(fmt.Sprintf("SELECT * FROM %sdata_null%s where id=?", Q, Q), 3).QueryRows(&dnList) @@ -1894,7 +1896,7 @@ func TestRawQueryRow(t *testing.T) { throwFail(t, AssertIs(row.Id, 4)) throwFail(t, AssertIs(row.EmbedField.Email, "nobody@gmail.com")) - // test for sql.Null* fields + // test for sql.Null* Fields nData := &DataNull{ NullString: sql.NullString{String: "test sql.null", Valid: true}, NullBool: sql.NullBool{Bool: true, Valid: true}, @@ -2003,7 +2005,7 @@ func TestQueryRows(t *testing.T) { throwFailNow(t, AssertIs(l[1].UserName, "astaxie")) throwFailNow(t, AssertIs(l[1].Age, 30)) - // test for sql.Null* fields + // test for sql.Null* Fields nData := &DataNull{ NullString: sql.NullString{String: "test sql.null", Valid: true}, NullBool: sql.NullBool{Bool: true, Valid: true}, @@ -2616,7 +2618,7 @@ func TestSnake(t *testing.T) { "tag_666Name": "tag_666_name", } for name, want := range cases { - got := snakeString(name) + got := models.SnakeString(name) throwFail(t, AssertIs(got, want)) } } @@ -2637,10 +2639,10 @@ func TestIgnoreCaseTag(t *testing.T) { if t == nil { return } - throwFail(t, AssertIs(info.fields.GetByName("NOO").column, "n")) - throwFail(t, AssertIs(info.fields.GetByName("Name01").null, true)) - throwFail(t, AssertIs(info.fields.GetByName("Name02").column, "Name")) - throwFail(t, AssertIs(info.fields.GetByName("Name03").column, "name")) + throwFail(t, AssertIs(info.Fields.GetByName("NOO").Column, "n")) + throwFail(t, AssertIs(info.Fields.GetByName("Name01").Null, true)) + throwFail(t, AssertIs(info.Fields.GetByName("Name02").Column, "Name")) + throwFail(t, AssertIs(info.Fields.GetByName("Name03").Column, "name")) } func TestInsertOrUpdate(t *testing.T) { @@ -2934,9 +2936,9 @@ func TestDebugLog(t *testing.T) { func captureDebugLogOutput(f func()) string { var buf bytes.Buffer - DebugLog.SetOutput(&buf) + logs.DebugLog.SetOutput(&buf) defer func() { - DebugLog.SetOutput(os.Stderr) + logs.DebugLog.SetOutput(os.Stderr) }() f() return buf.String() diff --git a/client/orm/qb_mysql.go b/client/orm/qb_mysql.go index 19130496..df65e11d 100644 --- a/client/orm/qb_mysql.go +++ b/client/orm/qb_mysql.go @@ -28,7 +28,7 @@ type MySQLQueryBuilder struct { tokens []string } -// Select will join the fields +// Select will join the Fields func (qb *MySQLQueryBuilder) Select(fields ...string) QueryBuilder { qb.tokens = append(qb.tokens, "SELECT", strings.Join(fields, CommaSpace)) return qb @@ -94,7 +94,7 @@ func (qb *MySQLQueryBuilder) In(vals ...string) QueryBuilder { return qb } -// OrderBy join the Order by fields +// OrderBy join the Order by Fields func (qb *MySQLQueryBuilder) OrderBy(fields ...string) QueryBuilder { qb.tokens = append(qb.tokens, "ORDER BY", strings.Join(fields, CommaSpace)) return qb @@ -124,7 +124,7 @@ func (qb *MySQLQueryBuilder) Offset(offset int) QueryBuilder { return qb } -// GroupBy join the Group by fields +// GroupBy join the Group by Fields func (qb *MySQLQueryBuilder) GroupBy(fields ...string) QueryBuilder { qb.tokens = append(qb.tokens, "GROUP BY", strings.Join(fields, CommaSpace)) return qb diff --git a/client/orm/qb_postgres.go b/client/orm/qb_postgres.go index d7f21692..3e5ec1c6 100644 --- a/client/orm/qb_postgres.go +++ b/client/orm/qb_postgres.go @@ -19,7 +19,7 @@ func processingStr(str []string) string { return s } -// Select will join the fields +// Select will join the Fields func (qb *PostgresQueryBuilder) Select(fields ...string) QueryBuilder { var str string n := len(fields) @@ -121,7 +121,7 @@ func (qb *PostgresQueryBuilder) In(vals ...string) QueryBuilder { return qb } -// OrderBy join the Order by fields +// OrderBy join the Order by Fields func (qb *PostgresQueryBuilder) OrderBy(fields ...string) QueryBuilder { str := processingStr(fields) qb.tokens = append(qb.tokens, "ORDER BY", str) @@ -152,7 +152,7 @@ func (qb *PostgresQueryBuilder) Offset(offset int) QueryBuilder { return qb } -// GroupBy join the Group by fields +// GroupBy join the Group by Fields func (qb *PostgresQueryBuilder) GroupBy(fields ...string) QueryBuilder { str := processingStr(fields) qb.tokens = append(qb.tokens, "GROUP BY", str) diff --git a/client/orm/types.go b/client/orm/types.go index df50a500..649d29fc 100644 --- a/client/orm/types.go +++ b/client/orm/types.go @@ -20,19 +20,23 @@ import ( "reflect" "time" + "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/beego/beego/v2/client/orm/clauses/order_clause" "github.com/beego/beego/v2/core/utils" ) -// TableNaming is usually used by model +// TableNameI is usually used by model // when you custom your table name, please implement this interfaces // for example: -// type User struct { -// ... -// } -// func (u *User) TableName() string { -// return "USER_TABLE" -// } +// +// type User struct { +// ... +// } +// +// func (u *User) TableName() string { +// return "USER_TABLE" +// } type TableNameI interface { TableName() string } @@ -40,12 +44,14 @@ type TableNameI interface { // TableEngineI is usually used by model // when you want to use specific engine, like myisam, you can implement this interface // for example: -// type User struct { -// ... -// } -// func (u *User) TableEngine() string { -// return "myisam" -// } +// +// type User struct { +// ... +// } +// +// func (u *User) TableEngine() string { +// return "myisam" +// } type TableEngineI interface { TableEngine() string } @@ -53,12 +59,14 @@ type TableEngineI interface { // TableIndexI is usually used by model // when you want to create indexes, you can implement this interface // for example: -// type User struct { -// ... -// } -// func (u *User) TableIndex() [][]string { -// return [][]string{{"Name"}} -// } +// +// type User struct { +// ... +// } +// +// func (u *User) TableIndex() [][]string { +// return [][]string{{"Name"}} +// } type TableIndexI interface { TableIndex() [][]string } @@ -66,12 +74,14 @@ type TableIndexI interface { // TableUniqueI is usually used by model // when you want to create unique indexes, you can implement this interface // for example: -// type User struct { -// ... -// } -// func (u *User) TableUnique() [][]string { -// return [][]string{{"Email"}} -// } +// +// type User struct { +// ... +// } +// +// func (u *User) TableUnique() [][]string { +// return [][]string{{"Email"}} +// } type TableUniqueI interface { TableUnique() [][]string } @@ -87,22 +97,16 @@ type Driver interface { Type() DriverType } -// Fielder define field info -type Fielder interface { - String() string - FieldType() int - SetRaw(interface{}) error - RawValue() interface{} -} +type Fielder = models.Fielder type TxBeginner interface { - // self control transaction + // Begin self control transaction Begin() (TxOrmer, error) BeginWithCtx(ctx context.Context) (TxOrmer, error) BeginWithOpts(opts *sql.TxOptions) (TxOrmer, error) BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxOrmer, error) - // closure control transaction + // DoTx closure control transaction DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error @@ -138,27 +142,27 @@ type txEnder interface { RollbackUnlessCommit() error } -// Data Manipulation Language +// DML Data Manipulation Language type DML interface { - // insert model data to database + // Insert insert model data to database // for example: // user := new(User) // id, err = Ormer.Insert(user) // user must be a pointer and Insert will set user's pk field Insert(md interface{}) (int64, error) InsertWithCtx(ctx context.Context, md interface{}) (int64, error) - // mysql:InsertOrUpdate(model) or InsertOrUpdate(model,"colu=colu+value") + // InsertOrUpdate mysql:InsertOrUpdate(model) or InsertOrUpdate(model,"colu=colu+value") // if colu type is integer : can use(+-*/), string : convert(colu,"value") // postgres: InsertOrUpdate(model,"conflictColumnName") or InsertOrUpdate(model,"conflictColumnName","colu=colu+value") // if colu type is integer : can use(+-*/), string : colu || "value" InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error) InsertOrUpdateWithCtx(ctx context.Context, md interface{}, colConflitAndArgs ...string) (int64, error) - // insert some models to database + // InsertMulti inserts some models to database InsertMulti(bulk int, mds interface{}) (int64, error) InsertMultiWithCtx(ctx context.Context, bulk int, mds interface{}) (int64, error) - // update model to database. - // cols set the columns those want to update. - // find model by Id(pk) field and update columns specified by fields, if cols is null then update all columns + // Update updates model to database. + // cols set the Columns those want to update. + // find model by Id(pk) field and update Columns specified by Fields, if cols is null then update all Columns // for example: // user := User{Id: 2} // user.Langs = append(user.Langs, "zh-CN", "en-US") @@ -167,11 +171,11 @@ type DML interface { // num, err = Ormer.Update(&user, "Langs", "Extra") Update(md interface{}, cols ...string) (int64, error) UpdateWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) - // delete model in database + // Delete deletes model in database Delete(md interface{}, cols ...string) (int64, error) DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) - // return a raw query seter for raw sql string. + // Raw return a raw query seter for raw sql string. // for example: // ormer.Raw("UPDATE `user` SET `user_name` = ? WHERE `user_name` = ?", "slene", "testing").Exec() // // update user testing's name to slene @@ -179,9 +183,9 @@ type DML interface { RawWithCtx(ctx context.Context, query string, args ...interface{}) RawSeter } -// Data Query Language +// DQL Data Query Language type DQL interface { - // read data to model + // Read reads data to model // for example: // this will find User by Id field // u = &User{Id: user.Id} @@ -192,16 +196,16 @@ type DQL interface { Read(md interface{}, cols ...string) error ReadWithCtx(ctx context.Context, md interface{}, cols ...string) error - // Like Read(), but with "FOR UPDATE" clause, useful in transaction. + // ReadForUpdate Like Read(), but with "FOR UPDATE" clause, useful in transaction. // Some databases are not support this feature. ReadForUpdate(md interface{}, cols ...string) error ReadForUpdateWithCtx(ctx context.Context, md interface{}, cols ...string) error - // Try to read a row from the database, or insert one if it doesn't exist + // ReadOrCreate Try to read a row from the database, or insert one if it doesn't exist ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) ReadOrCreateWithCtx(ctx context.Context, md interface{}, col1 string, cols ...string) (bool, int64, error) - // load related models to md model. + // LoadRelated load related models to md model. // args are limit, offset int and order string. // // example: @@ -216,20 +220,20 @@ type DQL interface { LoadRelated(md interface{}, name string, args ...utils.KV) (int64, error) LoadRelatedWithCtx(ctx context.Context, md interface{}, name string, args ...utils.KV) (int64, error) - // create a models to models queryer + // QueryM2M create a models to models queryer // for example: // post := Post{Id: 4} // m2m := Ormer.QueryM2M(&post, "Tags") QueryM2M(md interface{}, name string) QueryM2Mer - // NOTE: this method is deprecated, context parameter will not take effect. + // QueryM2MWithCtx NOTE: this method is deprecated, context parameter will not take effect. // Use context.Context directly on methods with `WithCtx` suffix such as InsertWithCtx/UpdateWithCtx QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer - // return a QuerySeter for table operations. + // QueryTable return a QuerySeter for table operations. // table name can be string or struct. // e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)), QueryTable(ptrStructOrTableName interface{}) QuerySeter - // NOTE: this method is deprecated, context parameter will not take effect. + // QueryTableWithCtx NOTE: this method is deprecated, context parameter will not take effect. // Use context.Context directly on methods with `WithCtx` suffix such as InsertWithCtx/UpdateWithCtx QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter @@ -270,7 +274,7 @@ type Inserter interface { // QuerySeter query seter type QuerySeter interface { - // add condition expression to QuerySeter. + // Filter add condition expression to QuerySeter. // for example: // filter by UserName == 'slene' // qs.Filter("UserName", "slene") @@ -279,22 +283,22 @@ type QuerySeter interface { // // time compare // qs.Filter("created", time.Now()) Filter(string, ...interface{}) QuerySeter - // add raw sql to querySeter. + // FilterRaw add raw sql to querySeter. // for example: // qs.FilterRaw("user_id IN (SELECT id FROM profile WHERE age>=18)") // //sql-> WHERE user_id IN (SELECT id FROM profile WHERE age>=18) FilterRaw(string, string) QuerySeter - // add NOT condition to querySeter. + // Exclude add NOT condition to querySeter. // have the same usage as Filter Exclude(string, ...interface{}) QuerySeter - // set condition to QuerySeter. + // SetCond set condition to QuerySeter. // sql's where condition // cond := orm.NewCondition() // cond1 := cond.And("profile__isnull", false).AndNot("status__in", 1).Or("profile__age__gt", 2000) // //sql-> WHERE T0.`profile_id` IS NOT NULL AND NOT T0.`Status` IN (?) OR T1.`age` > 2000 // num, err := qs.SetCond(cond1).Count() SetCond(*Condition) QuerySeter - // get condition from QuerySeter. + // GetCond get condition from QuerySeter. // sql's where condition // cond := orm.NewCondition() // cond = cond.And("profile__isnull", false).AndNot("status__in", 1) @@ -304,7 +308,7 @@ type QuerySeter interface { // //sql-> WHERE T0.`profile_id` IS NOT NULL AND NOT T0.`Status` IN (?) OR T1.`age` > 2000 // num, err := qs.SetCond(cond).Count() GetCond() *Condition - // add LIMIT value. + // Limit add LIMIT value. // args[0] means offset, e.g. LIMIT num,offset. // if Limit <= 0 then Limit will be set to default limit ,eg 1000 // if QuerySeter doesn't call Limit, the sql's Limit will be set to default limit, eg 1000 @@ -312,19 +316,19 @@ type QuerySeter interface { // qs.Limit(10, 2) // // sql-> limit 10 offset 2 Limit(limit interface{}, args ...interface{}) QuerySeter - // add OFFSET value + // Offset add OFFSET value // same as Limit function's args[0] Offset(offset interface{}) QuerySeter - // add GROUP BY expression + // GroupBy add GROUP BY expression // for example: // qs.GroupBy("id") GroupBy(exprs ...string) QuerySeter - // add ORDER expression. + // OrderBy add ORDER expression. // "column" means ASC, "-column" means DESC. // for example: // qs.OrderBy("-status") OrderBy(exprs ...string) QuerySeter - // add ORDER expression by order clauses + // OrderClauses add ORDER expression by order clauses // for example: // OrderClauses( // order_clause.Clause( @@ -346,50 +350,50 @@ type QuerySeter interface { // order_clause.Raw(),//default false.if true, do not check field is valid or not // )) OrderClauses(orders ...*order_clause.Order) QuerySeter - // add FORCE INDEX expression. + // ForceIndex add FORCE INDEX expression. // for example: // qs.ForceIndex(`idx_name1`,`idx_name2`) // ForceIndex, UseIndex , IgnoreIndex are mutually exclusive ForceIndex(indexes ...string) QuerySeter - // add USE INDEX expression. + // UseIndex add USE INDEX expression. // for example: // qs.UseIndex(`idx_name1`,`idx_name2`) // ForceIndex, UseIndex , IgnoreIndex are mutually exclusive UseIndex(indexes ...string) QuerySeter - // add IGNORE INDEX expression. + // IgnoreIndex add IGNORE INDEX expression. // for example: // qs.IgnoreIndex(`idx_name1`,`idx_name2`) // ForceIndex, UseIndex , IgnoreIndex are mutually exclusive IgnoreIndex(indexes ...string) QuerySeter - // set relation model to query together. + // RelatedSel set relation model to query together. // it will query relation models and assign to parent model. // for example: - // // will load all related fields use left join . + // // will load all related Fields use left join . // qs.RelatedSel().One(&user) // // will load related field only profile // qs.RelatedSel("profile").One(&user) // user.Profile.Age = 32 RelatedSel(params ...interface{}) QuerySeter - // Set Distinct + // Distinct Set Distinct // for example: // o.QueryTable("policy").Filter("Groups__Group__Users__User", user). // Distinct(). // All(&permissions) Distinct() QuerySeter - // set FOR UPDATE to query. + // ForUpdate set FOR UPDATE to query. // for example: // o.QueryTable("user").Filter("uid", uid).ForUpdate().All(&users) ForUpdate() QuerySeter - // return QuerySeter execution result number + // Count returns QuerySeter execution result number // for example: // num, err = qs.Filter("profile__age__gt", 28).Count() Count() (int64, error) CountWithCtx(context.Context) (int64, error) - // check result empty or not after QuerySeter executed + // Exist check result empty or not after QuerySeter executed // the same as QuerySeter.Count > 0 Exist() bool ExistWithCtx(context.Context) bool - // execute update with parameters + // Update execute update with parameters // for example: // num, err = qs.Filter("user_name", "slene").Update(Params{ // "Nums": ColValue(Col_Minus, 50), @@ -399,13 +403,13 @@ type QuerySeter interface { // }) // user slene's name will change to slene2 Update(values Params) (int64, error) UpdateWithCtx(ctx context.Context, values Params) (int64, error) - // delete from table + // Delete delete from table // for example: // num ,err = qs.Filter("user_name__in", "testing1", "testing2").Delete() // //delete two user who's name is testing1 or testing2 Delete() (int64, error) DeleteWithCtx(context.Context) (int64, error) - // return an insert queryer. + // PrepareInsert return an insert queryer. // it can be used in times. // example: // i,err := sq.PrepareInsert() @@ -414,21 +418,21 @@ type QuerySeter interface { // err = i.Close() //don't forget call Close PrepareInsert() (Inserter, error) PrepareInsertWithCtx(context.Context) (Inserter, error) - // query all data and map to containers. - // cols means the columns when querying. + // All query all data and map to containers. + // cols means the Columns when querying. // for example: // var users []*User // qs.All(&users) // users[0],users[1],users[2] ... All(container interface{}, cols ...string) (int64, error) AllWithCtx(ctx context.Context, container interface{}, cols ...string) (int64, error) - // query one row data and map to containers. - // cols means the columns when querying. + // One query one row data and map to containers. + // cols means the Columns when querying. // for example: // var user User // qs.One(&user) //user.UserName == "slene" One(container interface{}, cols ...string) error OneWithCtx(ctx context.Context, container interface{}, cols ...string) error - // query all data and map to []map[string]interface. + // Values query all data and map to []map[string]interface. // expres means condition expression. // it converts data to []map[column]value. // for example: @@ -436,21 +440,21 @@ type QuerySeter interface { // qs.Values(&maps) //maps[0]["UserName"]=="slene" Values(results *[]Params, exprs ...string) (int64, error) ValuesWithCtx(ctx context.Context, results *[]Params, exprs ...string) (int64, error) - // query all data and map to [][]interface + // ValuesList query all data and map to [][]interface // it converts data to [][column_index]value // for example: // var list []ParamsList // qs.ValuesList(&list) // list[0][1] == "slene" ValuesList(results *[]ParamsList, exprs ...string) (int64, error) ValuesListWithCtx(ctx context.Context, results *[]ParamsList, exprs ...string) (int64, error) - // query all data and map to []interface. + // ValuesFlat query all data and map to []interface. // it's designed for one column record set, auto change to []value, not [][column]value. // for example: // var list ParamsList // qs.ValuesFlat(&list, "UserName") // list[0] == "slene" ValuesFlat(result *ParamsList, expr string) (int64, error) ValuesFlatWithCtx(ctx context.Context, result *ParamsList, expr string) (int64, error) - // query all rows into map[string]interface with specify key and value column name. + // RowsToMap query all rows into map[string]interface with specify key and value column name. // keyCol = "name", valueCol = "value" // table data // name | value @@ -461,7 +465,7 @@ type QuerySeter interface { // "found": 200, // } RowsToMap(result *Params, keyCol, valueCol string) (int64, error) - // query all rows into struct with specify key and value column name. + // RowsToStruct query all rows into struct with specify key and value column name. // keyCol = "name", valueCol = "value" // table data // name | value @@ -472,7 +476,7 @@ type QuerySeter interface { // Found int // } RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error) - // aggregate func. + // Aggregate aggregate func. // for example: // type result struct { // DeptName string @@ -486,7 +490,7 @@ type QuerySeter interface { // QueryM2Mer model to model query struct // all operations are on the m2m table only, will not affect the origin model table type QueryM2Mer interface { - // add models to origin models when creating queryM2M. + // Add adds models to origin models when creating queryM2M. // example: // m2m := orm.QueryM2M(post,"Tag") // m2m.Add(&Tag1{},&Tag2{}) @@ -499,20 +503,20 @@ type QueryM2Mer interface { // make sure the relation is defined in post model struct tag. Add(...interface{}) (int64, error) AddWithCtx(context.Context, ...interface{}) (int64, error) - // remove models following the origin model relationship + // Remove removes models following the origin model relationship // only delete rows from m2m table // for example: // tag3 := &Tag{Id:5,Name: "TestTag3"} // num, err = m2m.Remove(tag3) Remove(...interface{}) (int64, error) RemoveWithCtx(context.Context, ...interface{}) (int64, error) - // check model is existed in relationship of origin model + // Exist checks model is existed in relationship of origin model Exist(interface{}) bool ExistWithCtx(context.Context, interface{}) bool - // clean all models in related of origin model + // Clear cleans all models in related of origin model Clear() (int64, error) ClearWithCtx(context.Context) (int64, error) - // count all related models of origin model + // Count counts all related models of origin model Count() (int64, error) CountWithCtx(context.Context) (int64, error) } @@ -526,35 +530,36 @@ type RawPreparer interface { // RawSeter raw query seter // create From Ormer.Raw // for example: -// sql := fmt.Sprintf("SELECT %sid%s,%sname%s FROM %suser%s WHERE id = ?",Q,Q,Q,Q,Q,Q) -// rs := Ormer.Raw(sql, 1) +// +// sql := fmt.Sprintf("SELECT %sid%s,%sname%s FROM %suser%s WHERE id = ?",Q,Q,Q,Q,Q,Q) +// rs := Ormer.Raw(sql, 1) type RawSeter interface { - // execute sql and get result + // Exec execute sql and get result Exec() (sql.Result, error) - // query data and map to container + // QueryRow query data and map to container // for example: // var name string // var id int // rs.QueryRow(&id,&name) // id==2 name=="slene" QueryRow(containers ...interface{}) error - // query data rows and map to container + // QueryRows query data rows and map to container // var ids []int // var names []int // query = fmt.Sprintf("SELECT 'id','name' FROM %suser%s", Q, Q) // num, err = dORM.Raw(query).QueryRows(&ids,&names) // ids=>{1,2},names=>{"nobody","slene"} QueryRows(containers ...interface{}) (int64, error) SetArgs(...interface{}) RawSeter - // query data to []map[string]interface + // Values query data to []map[string]interface // see QuerySeter's Values Values(container *[]Params, cols ...string) (int64, error) - // query data to [][]interface + // ValuesList query data to [][]interface // see QuerySeter's ValuesList ValuesList(container *[]ParamsList, cols ...string) (int64, error) - // query data to []interface + // ValuesFlat query data to []interface // see QuerySeter's ValuesFlat ValuesFlat(container *ParamsList, cols ...string) (int64, error) - // query all rows into map[string]interface with specify key and value column name. + // RowsToMap query all rows into map[string]interface with specify key and value column name. // keyCol = "name", valueCol = "value" // table data // name | value @@ -565,7 +570,7 @@ type RawSeter interface { // "found": 200, // } RowsToMap(result *Params, keyCol, valueCol string) (int64, error) - // query all rows into struct with specify key and value column name. + // RowsToStruct query all rows into struct with specify key and value column name. // keyCol = "name", valueCol = "value" // table data // name | value @@ -577,7 +582,7 @@ type RawSeter interface { // } RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error) - // return prepared raw statement for used in times. + // Prepare return prepared raw statement for used in times. // for example: // pre, err := dORM.Raw("INSERT INTO tag (name) VALUES (?)").Prepare() // r, err := pre.Exec("name1") // INSERT INTO tag (name) VALUES (`name1`) @@ -617,32 +622,32 @@ type dbQuerier interface { // base database struct type dbBaser interface { - Read(context.Context, dbQuerier, *modelInfo, reflect.Value, *time.Location, []string, bool) error - ReadBatch(context.Context, dbQuerier, *querySet, *modelInfo, *Condition, interface{}, *time.Location, []string) (int64, error) - Count(context.Context, dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error) - ReadValues(context.Context, dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}, *time.Location) (int64, error) + Read(context.Context, dbQuerier, *models.ModelInfo, reflect.Value, *time.Location, []string, bool) error + ReadBatch(context.Context, dbQuerier, *querySet, *models.ModelInfo, *Condition, interface{}, *time.Location, []string) (int64, error) + Count(context.Context, dbQuerier, *querySet, *models.ModelInfo, *Condition, *time.Location) (int64, error) + ReadValues(context.Context, dbQuerier, *querySet, *models.ModelInfo, *Condition, []string, interface{}, *time.Location) (int64, error) - Insert(context.Context, dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error) - InsertOrUpdate(context.Context, dbQuerier, *modelInfo, reflect.Value, *alias, ...string) (int64, error) - InsertMulti(context.Context, dbQuerier, *modelInfo, reflect.Value, int, *time.Location) (int64, error) - InsertValue(context.Context, dbQuerier, *modelInfo, bool, []string, []interface{}) (int64, error) - InsertStmt(context.Context, stmtQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error) + Insert(context.Context, dbQuerier, *models.ModelInfo, reflect.Value, *time.Location) (int64, error) + InsertOrUpdate(context.Context, dbQuerier, *models.ModelInfo, reflect.Value, *alias, ...string) (int64, error) + InsertMulti(context.Context, dbQuerier, *models.ModelInfo, reflect.Value, int, *time.Location) (int64, error) + InsertValue(context.Context, dbQuerier, *models.ModelInfo, bool, []string, []interface{}) (int64, error) + InsertStmt(context.Context, stmtQuerier, *models.ModelInfo, reflect.Value, *time.Location) (int64, error) - Update(context.Context, dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) (int64, error) - UpdateBatch(context.Context, dbQuerier, *querySet, *modelInfo, *Condition, Params, *time.Location) (int64, error) + Update(context.Context, dbQuerier, *models.ModelInfo, reflect.Value, *time.Location, []string) (int64, error) + UpdateBatch(context.Context, dbQuerier, *querySet, *models.ModelInfo, *Condition, Params, *time.Location) (int64, error) - Delete(context.Context, dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) (int64, error) - DeleteBatch(context.Context, dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error) + Delete(context.Context, dbQuerier, *models.ModelInfo, reflect.Value, *time.Location, []string) (int64, error) + DeleteBatch(context.Context, dbQuerier, *querySet, *models.ModelInfo, *Condition, *time.Location) (int64, error) SupportUpdateJoin() bool OperatorSQL(string) string - GenerateOperatorSQL(*modelInfo, *fieldInfo, string, []interface{}, *time.Location) (string, []interface{}) - GenerateOperatorLeftCol(*fieldInfo, string, *string) - PrepareInsert(context.Context, dbQuerier, *modelInfo) (stmtQuerier, string, error) + GenerateOperatorSQL(*models.ModelInfo, *models.FieldInfo, string, []interface{}, *time.Location) (string, []interface{}) + GenerateOperatorLeftCol(*models.FieldInfo, string, *string) + PrepareInsert(context.Context, dbQuerier, *models.ModelInfo) (stmtQuerier, string, error) MaxLimit() uint64 TableQuote() string ReplaceMarks(*string) - HasReturningID(*modelInfo, *string) bool + HasReturningID(*models.ModelInfo, *string) bool TimeFromDB(*time.Time, *time.Location) TimeToDB(*time.Time, *time.Location) DbTypes() map[string]string @@ -651,8 +656,8 @@ type dbBaser interface { ShowTablesQuery() string ShowColumnsQuery(string) string IndexExists(context.Context, dbQuerier, string, string) bool - collectFieldValue(*modelInfo, *fieldInfo, reflect.Value, bool, *time.Location) (interface{}, error) - setval(context.Context, dbQuerier, *modelInfo, []string) error + collectFieldValue(*models.ModelInfo, *models.FieldInfo, reflect.Value, bool, *time.Location) (interface{}, error) + setval(context.Context, dbQuerier, *models.ModelInfo, []string) error GenerateSpecifyIndex(tableName string, useIndex int, indexes []string) string } diff --git a/client/orm/utils.go b/client/orm/utils.go index 8d05c080..40a818d6 100644 --- a/client/orm/utils.go +++ b/client/orm/utils.go @@ -15,305 +15,15 @@ package orm import ( - "fmt" - "math/big" - "reflect" - "strconv" - "strings" - "time" + "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/beego/beego/v2/client/orm/internal/utils" ) -type fn func(string) string +type StrTo = utils.StrTo -var ( - nameStrategyMap = map[string]fn{ - defaultNameStrategy: snakeString, - SnakeAcronymNameStrategy: snakeStringWithAcronym, - } - defaultNameStrategy = "snakeString" - SnakeAcronymNameStrategy = "snakeStringWithAcronym" - nameStrategy = defaultNameStrategy -) - -// StrTo is the target string -type StrTo string - -// Set string -func (f *StrTo) Set(v string) { - if v != "" { - *f = StrTo(v) - } else { - f.Clear() - } -} - -// Clear string -func (f *StrTo) Clear() { - *f = StrTo(rune(0x1E)) -} - -// Exist check string exist -func (f StrTo) Exist() bool { - return string(f) != string(rune(0x1E)) -} - -// Bool string to bool -func (f StrTo) Bool() (bool, error) { - return strconv.ParseBool(f.String()) -} - -// Float32 string to float32 -func (f StrTo) Float32() (float32, error) { - v, err := strconv.ParseFloat(f.String(), 32) - return float32(v), err -} - -// Float64 string to float64 -func (f StrTo) Float64() (float64, error) { - return strconv.ParseFloat(f.String(), 64) -} - -// Int string to int -func (f StrTo) Int() (int, error) { - v, err := strconv.ParseInt(f.String(), 10, 32) - return int(v), err -} - -// Int8 string to int8 -func (f StrTo) Int8() (int8, error) { - v, err := strconv.ParseInt(f.String(), 10, 8) - return int8(v), err -} - -// Int16 string to int16 -func (f StrTo) Int16() (int16, error) { - v, err := strconv.ParseInt(f.String(), 10, 16) - return int16(v), err -} - -// Int32 string to int32 -func (f StrTo) Int32() (int32, error) { - v, err := strconv.ParseInt(f.String(), 10, 32) - return int32(v), err -} - -// Int64 string to int64 -func (f StrTo) Int64() (int64, error) { - v, err := strconv.ParseInt(f.String(), 10, 64) - if err != nil { - i := new(big.Int) - ni, ok := i.SetString(f.String(), 10) // octal - if !ok { - return v, err - } - return ni.Int64(), nil - } - return v, err -} - -// Uint string to uint -func (f StrTo) Uint() (uint, error) { - v, err := strconv.ParseUint(f.String(), 10, 32) - return uint(v), err -} - -// Uint8 string to uint8 -func (f StrTo) Uint8() (uint8, error) { - v, err := strconv.ParseUint(f.String(), 10, 8) - return uint8(v), err -} - -// Uint16 string to uint16 -func (f StrTo) Uint16() (uint16, error) { - v, err := strconv.ParseUint(f.String(), 10, 16) - return uint16(v), err -} - -// Uint32 string to uint32 -func (f StrTo) Uint32() (uint32, error) { - v, err := strconv.ParseUint(f.String(), 10, 32) - return uint32(v), err -} - -// Uint64 string to uint64 -func (f StrTo) Uint64() (uint64, error) { - v, err := strconv.ParseUint(f.String(), 10, 64) - if err != nil { - i := new(big.Int) - ni, ok := i.SetString(f.String(), 10) - if !ok { - return v, err - } - return ni.Uint64(), nil - } - return v, err -} - -// String string to string -func (f StrTo) String() string { - if f.Exist() { - return string(f) - } - return "" -} - -// ToStr interface to string -func ToStr(value interface{}, args ...int) (s string) { - switch v := value.(type) { - case bool: - s = strconv.FormatBool(v) - case float32: - s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32)) - case float64: - s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64)) - case int: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int8: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int16: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int32: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int64: - s = strconv.FormatInt(v, argInt(args).Get(0, 10)) - case uint: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint8: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint16: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint32: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint64: - s = strconv.FormatUint(v, argInt(args).Get(0, 10)) - case string: - s = v - case []byte: - s = string(v) - default: - s = fmt.Sprintf("%v", v) - } - return s -} - -// ToInt64 interface to int64 -func ToInt64(value interface{}) (d int64) { - val := reflect.ValueOf(value) - switch value.(type) { - case int, int8, int16, int32, int64: - d = val.Int() - case uint, uint8, uint16, uint32, uint64: - d = int64(val.Uint()) - default: - panic(fmt.Errorf("ToInt64 need numeric not `%T`", value)) - } - return -} - -func snakeStringWithAcronym(s string) string { - data := make([]byte, 0, len(s)*2) - num := len(s) - for i := 0; i < num; i++ { - d := s[i] - before := false - after := false - if i > 0 { - before = s[i-1] >= 'a' && s[i-1] <= 'z' - } - if i+1 < num { - after = s[i+1] >= 'a' && s[i+1] <= 'z' - } - if i > 0 && d >= 'A' && d <= 'Z' && (before || after) { - data = append(data, '_') - } - data = append(data, d) - } - return strings.ToLower(string(data)) -} - -// snake string, XxYy to xx_yy , XxYY to xx_y_y -func snakeString(s string) string { - data := make([]byte, 0, len(s)*2) - j := false - num := len(s) - for i := 0; i < num; i++ { - d := s[i] - if i > 0 && d >= 'A' && d <= 'Z' && j { - data = append(data, '_') - } - if d != '_' { - j = true - } - data = append(data, d) - } - return strings.ToLower(string(data)) -} - -// SetNameStrategy set different name strategy func SetNameStrategy(s string) { - if SnakeAcronymNameStrategy != s { - nameStrategy = defaultNameStrategy - } - nameStrategy = s -} - -// camel string, xx_yy to XxYy -func camelString(s string) string { - data := make([]byte, 0, len(s)) - flag, num := true, len(s)-1 - for i := 0; i <= num; i++ { - d := s[i] - if d == '_' { - flag = true - continue - } else if flag { - if d >= 'a' && d <= 'z' { - d = d - 32 - } - flag = false - } - data = append(data, d) - } - return string(data) -} - -type argString []string - -// get string by index from string slice -func (a argString) Get(i int, args ...string) (r string) { - if i >= 0 && i < len(a) { - r = a[i] - } else if len(args) > 0 { - r = args[0] - } - return -} - -type argInt []int - -// get int by index from int slice -func (a argInt) Get(i int, args ...int) (r int) { - if i >= 0 && i < len(a) { - r = a[i] - } - if len(args) > 0 { - r = args[0] - } - return -} - -// parse time to string with location -func timeParse(dateString, format string) (time.Time, error) { - tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) - return tp, err -} - -// get pointer indirect type -func indirectType(v reflect.Type) reflect.Type { - switch v.Kind() { - case reflect.Ptr: - return indirectType(v.Elem()) - default: - return v + if models.SnakeAcronymNameStrategy != s { + models.NameStrategy = models.DefaultNameStrategy } + models.NameStrategy = s } diff --git a/core/admin/healthcheck.go b/core/admin/healthcheck.go index ea155b86..077b1c53 100644 --- a/core/admin/healthcheck.go +++ b/core/admin/healthcheck.go @@ -17,16 +17,15 @@ // type DatabaseCheck struct { // } // -// func (dc *DatabaseCheck) Check() error { -// if dc.isConnected() { -// return nil -// } else { -// return errors.New("can't connect database") -// } -// } +// func (dc *DatabaseCheck) Check() error { +// if dc.isConnected() { +// return nil +// } else { +// return errors.New("can't connect database") +// } +// } // // AddHealthCheck("database",&DatabaseCheck{}) -// package admin // AdminCheckList holds health checker map diff --git a/core/config/config.go b/core/config/config.go index 1222fb49..145333f9 100644 --- a/core/config/config.go +++ b/core/config/config.go @@ -14,29 +14,31 @@ // Package config is used to parse config. // Usage: -// import "github.com/beego/beego/v2/core/config" +// +// import "github.com/beego/beego/v2/core/config" +// // Examples. // -// cnf, err := config.NewConfig("ini", "config.conf") +// cnf, err := config.NewConfig("ini", "config.conf") // -// cnf APIS: +// cnf APIS: // -// cnf.Set(key, val string) error -// cnf.String(key string) string -// cnf.Strings(key string) []string -// cnf.Int(key string) (int, error) -// cnf.Int64(key string) (int64, error) -// cnf.Bool(key string) (bool, error) -// cnf.Float(key string) (float64, error) -// cnf.DefaultString(key string, defaultVal string) string -// cnf.DefaultStrings(key string, defaultVal []string) []string -// cnf.DefaultInt(key string, defaultVal int) int -// cnf.DefaultInt64(key string, defaultVal int64) int64 -// cnf.DefaultBool(key string, defaultVal bool) bool -// cnf.DefaultFloat(key string, defaultVal float64) float64 -// cnf.DIY(key string) (interface{}, error) -// cnf.GetSection(section string) (map[string]string, error) -// cnf.SaveConfigFile(filename string) error +// cnf.Set(key, val string) error +// cnf.String(key string) string +// cnf.Strings(key string) []string +// cnf.Int(key string) (int, error) +// cnf.Int64(key string) (int64, error) +// cnf.Bool(key string) (bool, error) +// cnf.Float(key string) (float64, error) +// cnf.DefaultString(key string, defaultVal string) string +// cnf.DefaultStrings(key string, defaultVal []string) []string +// cnf.DefaultInt(key string, defaultVal int) int +// cnf.DefaultInt64(key string, defaultVal int64) int64 +// cnf.DefaultBool(key string, defaultVal bool) bool +// cnf.DefaultFloat(key string, defaultVal float64) float64 +// cnf.DIY(key string) (interface{}, error) +// cnf.GetSection(section string) (map[string]string, error) +// cnf.SaveConfigFile(filename string) error package config import ( @@ -266,6 +268,7 @@ func ExpandValueEnvForMap(m map[string]interface{}) map[string]interface{} { // // It accept value formats "${env}" , "${env||}}" , "${env||defaultValue}" , "defaultvalue". // Examples: +// // v1 := config.ExpandValueEnv("${GOPATH}") // return the GOPATH environment variable. // v2 := config.ExpandValueEnv("${GOAsta||/usr/local/go}") // return the default value "/usr/local/go/". // v3 := config.ExpandValueEnv("Astaxie") // return the value "Astaxie". diff --git a/core/config/env/env.go b/core/config/env/env.go index d745362a..8d3b2ae2 100644 --- a/core/config/env/env.go +++ b/core/config/env/env.go @@ -19,7 +19,6 @@ package env import ( "fmt" "go/build" - "io/ioutil" "os" "path/filepath" "strings" @@ -119,7 +118,7 @@ func GetRuntimeEnv(key string) (string, error) { } var runtimeEnv string - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) if err != nil { return "", err } diff --git a/core/config/env/env_test.go b/core/config/env/env_test.go index 1cd88147..eabff737 100644 --- a/core/config/env/env_test.go +++ b/core/config/env/env_test.go @@ -5,7 +5,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/core/config/ini.go b/core/config/ini.go index d4dea2e3..9f808d2c 100644 --- a/core/config/ini.go +++ b/core/config/ini.go @@ -20,7 +20,6 @@ import ( "context" "errors" "io" - "io/ioutil" "os" "os/user" "path/filepath" @@ -54,7 +53,7 @@ func (ini *IniConfig) Parse(name string) (Configer, error) { } func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) { - data, err := ioutil.ReadFile(name) + data, err := os.ReadFile(name) if err != nil { return nil, err } diff --git a/core/config/ini_test.go b/core/config/ini_test.go index 37ec7203..302c7ecd 100644 --- a/core/config/ini_test.go +++ b/core/config/ini_test.go @@ -16,7 +16,6 @@ package config import ( "fmt" - "io/ioutil" "os" "strings" "testing" @@ -173,7 +172,7 @@ name=mysql } defer os.Remove(name) - if data, err := ioutil.ReadFile(name); err != nil { + if data, err := os.ReadFile(name); err != nil { t.Fatal(err) } else { cfgData := string(data) diff --git a/core/config/json/json.go b/core/config/json/json.go index 098f0308..1d764733 100644 --- a/core/config/json/json.go +++ b/core/config/json/json.go @@ -18,7 +18,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "os" "strconv" "strings" @@ -40,7 +40,7 @@ func (js *JSONConfig) Parse(filename string) (config.Configer, error) { return nil, err } defer file.Close() - content, err := ioutil.ReadAll(file) + content, err := io.ReadAll(file) if err != nil { return nil, err } @@ -99,12 +99,12 @@ func (c *JSONConfigContainer) sub(key string) (map[string]interface{}, error) { } value, ok := c.data[key] if !ok { - return nil, errors.New(fmt.Sprintf("key is not found: %s", key)) + return nil, fmt.Errorf("key is not found: %s", key) } res, ok := value.(map[string]interface{}) if !ok { - return nil, errors.New(fmt.Sprintf("the type of value is invalid, key: %s", key)) + return nil, fmt.Errorf("the type of value is invalid, key: %s", key) } return res, nil } diff --git a/core/config/toml/toml.go b/core/config/toml/toml.go index b002e93e..297d16c8 100644 --- a/core/config/toml/toml.go +++ b/core/config/toml/toml.go @@ -15,7 +15,6 @@ package toml import ( - "io/ioutil" "os" "strings" @@ -32,7 +31,7 @@ type Config struct { // Parse accepts filename as the parameter func (c *Config) Parse(filename string) (config.Configer, error) { - ctx, err := ioutil.ReadFile(filename) + ctx, err := os.ReadFile(filename) if err != nil { return nil, err } diff --git a/core/config/xml/xml.go b/core/config/xml/xml.go index 173f2246..8aa7e26b 100644 --- a/core/config/xml/xml.go +++ b/core/config/xml/xml.go @@ -19,20 +19,19 @@ // go install github.com/beego/x2j. // // Usage: -// import( -// _ "github.com/beego/beego/v2/core/config/xml" -// "github.com/beego/beego/v2/core/config" -// ) // -// cnf, err := config.NewConfig("xml", "config.xml") +// import( +// _ "github.com/beego/beego/v2/core/config/xml" +// "github.com/beego/beego/v2/core/config" +// ) // +// cnf, err := config.NewConfig("xml", "config.xml") package xml import ( "encoding/xml" "errors" "fmt" - "io/ioutil" "os" "strconv" "strings" @@ -40,9 +39,10 @@ import ( "github.com/mitchellh/mapstructure" + "github.com/beego/x2j" + "github.com/beego/beego/v2/core/config" "github.com/beego/beego/v2/core/logs" - "github.com/beego/x2j" ) // Config is a xml config parser and implements Config interface. @@ -52,7 +52,7 @@ type Config struct{} // Parse returns a ConfigContainer with parsed xml config map. func (xc *Config) Parse(filename string) (config.Configer, error) { - context, err := ioutil.ReadFile(filename) + context, err := os.ReadFile(filename) if err != nil { return nil, err } @@ -119,11 +119,11 @@ func (c *ConfigContainer) sub(key string) (map[string]interface{}, error) { } value, ok := c.data[key] if !ok { - return nil, errors.New(fmt.Sprintf("the key is not found: %s", key)) + return nil, fmt.Errorf("the key is not found: %s", key) } res, ok := value.(map[string]interface{}) if !ok { - return nil, errors.New(fmt.Sprintf("the value of this key is not a structure: %s", key)) + return nil, fmt.Errorf("the value of this key is not a structure: %s", key) } return res, nil } diff --git a/core/config/yaml/yaml.go b/core/config/yaml/yaml.go index b18ce06b..ea54a1bb 100644 --- a/core/config/yaml/yaml.go +++ b/core/config/yaml/yaml.go @@ -14,19 +14,18 @@ // Package yaml for config provider // Usage: -// import( -// _ "github.com/beego/beego/v2/core/config/yaml" -// "github.com/beego/beego/v2/core/config" -// ) // -// cnf, err := config.NewConfig("yaml", "config.yaml") +// import( +// _ "github.com/beego/beego/v2/core/config/yaml" +// "github.com/beego/beego/v2/core/config" +// ) // +// cnf, err := config.NewConfig("yaml", "config.yaml") package yaml import ( "errors" "fmt" - "io/ioutil" "os" "strings" "sync" @@ -66,7 +65,7 @@ func (*Config) ParseData(data []byte) (config.Configer, error) { // ReadYmlReader Read yaml file to map. func ReadYmlReader(path string) (cnf map[string]interface{}, err error) { - buf, err := ioutil.ReadFile(path) + buf, err := os.ReadFile(path) if err != nil { return } diff --git a/core/logs/alils/log.pb.go b/core/logs/alils/log.pb.go index d57f36b3..f275c218 100755 --- a/core/logs/alils/log.pb.go +++ b/core/logs/alils/log.pb.go @@ -5,12 +5,11 @@ import ( "io" "math" - "github.com/gogo/protobuf/proto" github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" ) // Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal +var _ = github_com_gogo_protobuf_proto.Marshal var _ = fmt.Errorf @@ -34,7 +33,7 @@ type Log struct { func (m *Log) Reset() { *m = Log{} } // String returns the Compact Log -func (m *Log) String() string { return proto.CompactTextString(m) } +func (m *Log) String() string { return github_com_gogo_protobuf_proto.CompactTextString(m) } // ProtoMessage not implemented func (*Log) ProtoMessage() {} @@ -66,7 +65,7 @@ type LogContent struct { func (m *LogContent) Reset() { *m = LogContent{} } // String returns the compact text -func (m *LogContent) String() string { return proto.CompactTextString(m) } +func (m *LogContent) String() string { return github_com_gogo_protobuf_proto.CompactTextString(m) } // ProtoMessage not implemented func (*LogContent) ProtoMessage() {} @@ -100,7 +99,7 @@ type LogGroup struct { func (m *LogGroup) Reset() { *m = LogGroup{} } // String returns the compact text -func (m *LogGroup) String() string { return proto.CompactTextString(m) } +func (m *LogGroup) String() string { return github_com_gogo_protobuf_proto.CompactTextString(m) } // ProtoMessage not implemented func (*LogGroup) ProtoMessage() {} @@ -150,7 +149,7 @@ type LogGroupList struct { func (m *LogGroupList) Reset() { *m = LogGroupList{} } // String returns compact text -func (m *LogGroupList) String() string { return proto.CompactTextString(m) } +func (m *LogGroupList) String() string { return github_com_gogo_protobuf_proto.CompactTextString(m) } // ProtoMessage not implemented func (*LogGroupList) ProtoMessage() {} diff --git a/core/logs/alils/log_project.go b/core/logs/alils/log_project.go index f993003e..700b50c7 100755 --- a/core/logs/alils/log_project.go +++ b/core/logs/alils/log_project.go @@ -9,7 +9,7 @@ package alils import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httputil" ) @@ -45,13 +45,13 @@ func (p *LogProject) ListLogStore() (storeNames []string, err error) { "x-sls-bodyrawsize": "0", } - uri := fmt.Sprintf("/logstores") + uri := "/logstores" r, err := request(p, "GET", uri, h, nil) if err != nil { return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -96,7 +96,7 @@ func (p *LogProject) GetLogStore(name string) (s *LogStore, err error) { return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -156,7 +156,7 @@ func (p *LogProject) CreateLogStore(name string, ttl, shardCnt int) (err error) return } - body, err = ioutil.ReadAll(r.Body) + body, err = io.ReadAll(r.Body) if err != nil { return } @@ -188,7 +188,7 @@ func (p *LogProject) DeleteLogStore(name string) (err error) { return } - body, err := ioutil.ReadAll(r.Body) + body, err := io.ReadAll(r.Body) if err != nil { return } @@ -239,7 +239,7 @@ func (p *LogProject) UpdateLogStore(name string, ttl, shardCnt int) (err error) return } - body, err = ioutil.ReadAll(r.Body) + body, err = io.ReadAll(r.Body) if err != nil { return } @@ -277,7 +277,7 @@ func (p *LogProject) ListMachineGroup(offset, size int) (m []string, total int, return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -324,7 +324,7 @@ func (p *LogProject) GetMachineGroup(name string) (m *MachineGroup, err error) { return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -369,7 +369,7 @@ func (p *LogProject) CreateMachineGroup(m *MachineGroup) (err error) { return } - body, err = ioutil.ReadAll(r.Body) + body, err = io.ReadAll(r.Body) if err != nil { return } @@ -408,7 +408,7 @@ func (p *LogProject) UpdateMachineGroup(m *MachineGroup) (err error) { return } - body, err = ioutil.ReadAll(r.Body) + body, err = io.ReadAll(r.Body) if err != nil { return } @@ -440,7 +440,7 @@ func (p *LogProject) DeleteMachineGroup(name string) (err error) { return } - body, err := ioutil.ReadAll(r.Body) + body, err := io.ReadAll(r.Body) if err != nil { return } @@ -477,7 +477,7 @@ func (p *LogProject) ListConfig(offset, size int) (cfgNames []string, total int, return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -522,7 +522,7 @@ func (p *LogProject) GetConfig(name string) (c *LogConfig, err error) { return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -567,7 +567,7 @@ func (p *LogProject) UpdateConfig(c *LogConfig) (err error) { return } - body, err = ioutil.ReadAll(r.Body) + body, err = io.ReadAll(r.Body) if err != nil { return } @@ -606,7 +606,7 @@ func (p *LogProject) CreateConfig(c *LogConfig) (err error) { return } - body, err = ioutil.ReadAll(r.Body) + body, err = io.ReadAll(r.Body) if err != nil { return } @@ -638,7 +638,7 @@ func (p *LogProject) DeleteConfig(name string) (err error) { return } - body, err := ioutil.ReadAll(r.Body) + body, err := io.ReadAll(r.Body) if err != nil { return } @@ -670,7 +670,7 @@ func (p *LogProject) GetAppliedMachineGroups(confName string) (groupNames []stri return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -715,7 +715,7 @@ func (p *LogProject) GetAppliedConfigs(groupName string) (confNames []string, er return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -760,7 +760,7 @@ func (p *LogProject) ApplyConfigToMachineGroup(confName, groupName string) (err return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -792,7 +792,7 @@ func (p *LogProject) RemoveConfigFromMachineGroup(confName, groupName string) (e return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } diff --git a/core/logs/alils/log_store.go b/core/logs/alils/log_store.go index fd9d9eaf..4a6823ab 100755 --- a/core/logs/alils/log_store.go +++ b/core/logs/alils/log_store.go @@ -3,7 +3,7 @@ package alils import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httputil" "strconv" @@ -41,7 +41,7 @@ func (s *LogStore) ListShards() (shardIDs []int, err error) { return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -98,7 +98,7 @@ func (s *LogStore) PutLogs(lg *LogGroup) (err error) { return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -134,7 +134,7 @@ func (s *LogStore) GetCursor(shardID int, from string) (cursor string, err error return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } @@ -185,7 +185,7 @@ func (s *LogStore) GetLogsBytes(shardID int, cursor string, return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } diff --git a/core/logs/alils/machine_group.go b/core/logs/alils/machine_group.go index 101faeb4..b00c480e 100755 --- a/core/logs/alils/machine_group.go +++ b/core/logs/alils/machine_group.go @@ -3,7 +3,7 @@ package alils import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httputil" ) @@ -54,7 +54,7 @@ func (m *MachineGroup) ListMachines() (ms []*Machine, total int, err error) { return } - buf, err := ioutil.ReadAll(r.Body) + buf, err := io.ReadAll(r.Body) if err != nil { return } diff --git a/core/logs/es/es.go b/core/logs/es/es.go index a07ee83c..d1ba452d 100644 --- a/core/logs/es/es.go +++ b/core/logs/es/es.go @@ -81,7 +81,7 @@ func (el *esLogger) Init(config string) error { if len(el.Formatter) > 0 { fmtr, ok := logs.GetFormatter(el.Formatter) if !ok { - return errors.New(fmt.Sprintf("the formatter with name: %s not found", el.Formatter)) + return fmt.Errorf("the formatter with name: %s not found", el.Formatter) } el.formatter = fmtr } diff --git a/core/logs/file.go b/core/logs/file.go index 3234a674..b50369e7 100644 --- a/core/logs/file.go +++ b/core/logs/file.go @@ -110,15 +110,16 @@ func (w *fileLogWriter) SetFormatter(f LogFormatter) { // Init file logger with json config. // jsonConfig like: -// { -// "filename":"logs/beego.log", -// "maxLines":10000, -// "maxsize":1024, -// "daily":true, -// "maxDays":15, -// "rotate":true, -// "perm":"0600" -// } +// +// { +// "filename":"logs/beego.log", +// "maxLines":10000, +// "maxsize":1024, +// "daily":true, +// "maxDays":15, +// "rotate":true, +// "perm":"0600" +// } func (w *fileLogWriter) Init(config string) error { err := json.Unmarshal([]byte(config), w) if err != nil { diff --git a/core/logs/file_test.go b/core/logs/file_test.go index 6aac919a..d7ac2d21 100644 --- a/core/logs/file_test.go +++ b/core/logs/file_test.go @@ -17,7 +17,6 @@ package logs import ( "bufio" "fmt" - "io/ioutil" "os" "strconv" "testing" @@ -378,7 +377,7 @@ func testFileDailyRotate(t *testing.T, fn1, fn2 string) { if err != nil { t.FailNow() } - content, err := ioutil.ReadFile(file) + content, err := os.ReadFile(file) if err != nil { t.FailNow() } @@ -413,7 +412,7 @@ func testFileHourlyRotate(t *testing.T, fn1, fn2 string) { if err != nil { t.FailNow() } - content, err := ioutil.ReadFile(file) + content, err := os.ReadFile(file) if err != nil { t.FailNow() } diff --git a/core/logs/smtp.go b/core/logs/smtp.go index 40891a7c..10630070 100644 --- a/core/logs/smtp.go +++ b/core/logs/smtp.go @@ -47,6 +47,7 @@ func newSMTPWriter() Logger { // Init smtp writer with json config. // config like: +// // { // "username":"example@gmail.com", // "password:"password", diff --git a/core/utils/mail.go b/core/utils/mail.go index e685c449..0f1f95cc 100644 --- a/core/utils/mail.go +++ b/core/utils/mail.go @@ -120,7 +120,7 @@ func (e *Email) Bytes() ([]byte, error) { } // Create the body sections if e.Text != "" { - header.Set("Content-Type", fmt.Sprintf("text/plain; charset=UTF-8")) + header.Set("Content-Type", "text/plain; charset=UTF-8") header.Set("Content-Transfer-Encoding", "quoted-printable") if _, err := subWriter.CreatePart(header); err != nil { return nil, err @@ -131,7 +131,7 @@ func (e *Email) Bytes() ([]byte, error) { } } if e.HTML != "" { - header.Set("Content-Type", fmt.Sprintf("text/html; charset=UTF-8")) + header.Set("Content-Type", "text/html; charset=UTF-8") header.Set("Content-Transfer-Encoding", "quoted-printable") if _, err := subWriter.CreatePart(header); err != nil { return nil, err diff --git a/core/utils/pagination/doc.go b/core/utils/pagination/doc.go index 808301a5..78beccd3 100644 --- a/core/utils/pagination/doc.go +++ b/core/utils/pagination/doc.go @@ -2,53 +2,51 @@ Package pagination provides utilities to setup a paginator within the context of a http request. -Usage +# Usage In your beego.Controller: - package controllers + package controllers - import "github.com/beego/beego/v2/core/utils/pagination" + import "github.com/beego/beego/v2/core/utils/pagination" - type PostsController struct { - beego.Controller - } + type PostsController struct { + beego.Controller + } - func (this *PostsController) ListAllPosts() { - // sets this.Data["paginator"] with the current offset (from the url query param) - postsPerPage := 20 - paginator := pagination.SetPaginator(this.Ctx, postsPerPage, CountPosts()) - - // fetch the next 20 posts - this.Data["posts"] = ListPostsByOffsetAndLimit(paginator.Offset(), postsPerPage) - } + func (this *PostsController) ListAllPosts() { + // sets this.Data["paginator"] with the current offset (from the url query param) + postsPerPage := 20 + paginator := pagination.SetPaginator(this.Ctx, postsPerPage, CountPosts()) + // fetch the next 20 posts + this.Data["posts"] = ListPostsByOffsetAndLimit(paginator.Offset(), postsPerPage) + } In your view templates: - {{if .paginator.HasPages}} - - {{end}} - + {{if .paginator.HasPages}} + + {{end}} */ package pagination diff --git a/core/utils/pagination/paginator.go b/core/utils/pagination/paginator.go index c6db31e0..6a9ca7c4 100644 --- a/core/utils/pagination/paginator.go +++ b/core/utils/pagination/paginator.go @@ -78,11 +78,11 @@ func (p *Paginator) Page() int { // // Usage (in a view template): // -// {{range $index, $page := .paginator.Pages}} -// -// {{$page}} -// -// {{end}} +// {{range $index, $page := .paginator.Pages}} +// +// {{$page}} +// +// {{end}} func (p *Paginator) Pages() []int { if p.pageRange == nil && p.nums > 0 { var pages []int diff --git a/core/validation/util.go b/core/validation/util.go index 918b206c..69a43243 100644 --- a/core/validation/util.go +++ b/core/validation/util.go @@ -67,13 +67,15 @@ type CustomFunc func(v *Validation, obj interface{}, key string) // AddCustomFunc Add a custom function to validation // The name can not be: -// Clear -// HasErrors -// ErrorMap -// Error -// Check -// Valid -// NoMatch +// +// Clear +// HasErrors +// ErrorMap +// Error +// Check +// Valid +// NoMatch +// // If the name is same with exists function, it will replace the origin valid function func AddCustomFunc(name string, f CustomFunc) error { if unFuncs[name] { diff --git a/core/validation/validation.go b/core/validation/validation.go index a6e502c7..33d466fa 100644 --- a/core/validation/validation.go +++ b/core/validation/validation.go @@ -42,7 +42,6 @@ // log.Println(v.Error.Key, v.Error.Message) // } // } -// package validation import ( diff --git a/core/validation/validators.go b/core/validation/validators.go index c4ea1f51..3150fda5 100644 --- a/core/validation/validators.go +++ b/core/validation/validators.go @@ -64,26 +64,27 @@ var once sync.Once // SetDefaultMessage set default messages // if not set, the default messages are -// "Required": "Can not be empty", -// "Min": "Minimum is %d", -// "Max": "Maximum is %d", -// "Range": "Range is %d to %d", -// "MinSize": "Minimum size is %d", -// "MaxSize": "Maximum size is %d", -// "Length": "Required length is %d", -// "Alpha": "Must be valid alpha characters", -// "Numeric": "Must be valid numeric characters", -// "AlphaNumeric": "Must be valid alpha or numeric characters", -// "Match": "Must match %s", -// "NoMatch": "Must not match %s", -// "AlphaDash": "Must be valid alpha or numeric or dash(-_) characters", -// "Email": "Must be a valid email address", -// "IP": "Must be a valid ip address", -// "Base64": "Must be valid base64 characters", -// "Mobile": "Must be valid mobile number", -// "Tel": "Must be valid telephone number", -// "Phone": "Must be valid telephone or mobile phone number", -// "ZipCode": "Must be valid zipcode", +// +// "Required": "Can not be empty", +// "Min": "Minimum is %d", +// "Max": "Maximum is %d", +// "Range": "Range is %d to %d", +// "MinSize": "Minimum size is %d", +// "MaxSize": "Maximum size is %d", +// "Length": "Required length is %d", +// "Alpha": "Must be valid alpha characters", +// "Numeric": "Must be valid numeric characters", +// "AlphaNumeric": "Must be valid alpha or numeric characters", +// "Match": "Must match %s", +// "NoMatch": "Must not match %s", +// "AlphaDash": "Must be valid alpha or numeric or dash(-_) characters", +// "Email": "Must be a valid email address", +// "IP": "Must be a valid ip address", +// "Base64": "Must be valid base64 characters", +// "Mobile": "Must be valid mobile number", +// "Tel": "Must be valid telephone number", +// "Phone": "Must be valid telephone or mobile phone number", +// "ZipCode": "Must be valid zipcode", func SetDefaultMessage(msg map[string]string) { if len(msg) == 0 { return diff --git a/go.mod b/go.mod index 605e9729..eb7b6d34 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542 - github.com/bits-and-blooms/bloom/v3 v3.3.1 + github.com/bits-and-blooms/bloom/v3 v3.5.0 github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b github.com/casbin/casbin v1.9.1 github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 @@ -12,6 +12,7 @@ require ( github.com/elastic/go-elasticsearch/v6 v6.8.10 github.com/elazarl/go-bindata-assetfs v1.0.1 github.com/go-kit/kit v0.12.1-0.20220826005032-a7ba4fa4e289 + github.com/go-kit/log v0.2.1 github.com/go-redis/redis/v7 v7.4.0 github.com/go-sql-driver/mysql v1.7.0 github.com/gogo/protobuf v1.3.2 @@ -26,17 +27,18 @@ require ( github.com/opentracing/opentracing-go v1.2.0 github.com/pelletier/go-toml v1.9.2 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.15.1 + github.com/prometheus/client_golang v1.16.0 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec github.com/stretchr/testify v1.8.1 + github.com/valyala/bytebufferpool v1.0.0 go.etcd.io/etcd/client/v3 v3.5.9 go.opentelemetry.io/otel v1.11.2 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.2 go.opentelemetry.io/otel/sdk v1.11.2 go.opentelemetry.io/otel/trace v1.11.2 - golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd - golang.org/x/sync v0.1.0 + golang.org/x/crypto v0.10.0 + golang.org/x/sync v0.3.0 google.golang.org/grpc v1.41.0 google.golang.org/protobuf v1.30.0 gopkg.in/yaml.v3 v3.0.1 @@ -45,7 +47,7 @@ require ( require ( github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.4.0 // indirect + github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect @@ -54,7 +56,6 @@ require ( github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect - github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -64,7 +65,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0 // indirect github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d // indirect @@ -74,9 +75,9 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.7.0 // indirect go.uber.org/zap v1.19.1 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.9.0 // indirect + golang.org/x/text v0.10.0 // indirect google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 // indirect ) diff --git a/go.sum b/go.sum index ae4caa49..0d1d9182 100644 --- a/go.sum +++ b/go.sum @@ -13,11 +13,10 @@ github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLj github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.3.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bits-and-blooms/bitset v1.4.0 h1:+YZ8ePm+He2pU3dZlIZiOeAKfrBkXi1lSrXJ/Xzgbu8= -github.com/bits-and-blooms/bitset v1.4.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bits-and-blooms/bloom/v3 v3.3.1 h1:K2+A19bXT8gJR5mU7y+1yW6hsKfNCjcP2uNfLFKncjQ= -github.com/bits-and-blooms/bloom/v3 v3.3.1/go.mod h1:bhUUknWd5khVbTe4UgMCSiOOVJzr3tMoijSK3WwvW90= +github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= +github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bloom/v3 v3.5.0 h1:AKDvi1V3xJCmSR6QhcBfHbCN4Vf8FfxeWkMNQfmAGhY= +github.com/bits-and-blooms/bloom/v3 v3.5.0/go.mod h1:Y8vrn7nk1tPIlmLtW2ZPV+W7StdVMor6bC1xgpjMZFs= github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0= github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= github.com/casbin/casbin v1.9.1 h1:ucjbS5zTrmSLtH4XogqOG920Poe6QatdXtz1FEbApeM= @@ -160,15 +159,15 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= -github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= @@ -197,6 +196,8 @@ github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2K github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -229,8 +230,8 @@ go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -254,8 +255,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -265,8 +266,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -278,15 +279,15 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= diff --git a/server/web/admin.go b/server/web/admin.go index 56d2906f..10c80d6d 100644 --- a/server/web/admin.go +++ b/server/web/admin.go @@ -30,7 +30,8 @@ var beeAdminApp *adminApp // FilterMonitorFunc is default monitor filter when admin module is enable. // if this func returns, admin module records qps for this request by condition of this function logic. // usage: -// func MyFilterMonitor(method, requestPath string, t time.Duration, pattern string, statusCode int) bool { +// +// func MyFilterMonitor(method, requestPath string, t time.Duration, pattern string, statusCode int) bool { // if method == "POST" { // return false // } @@ -41,8 +42,8 @@ var beeAdminApp *adminApp // return false // } // return true -// } -// beego.FilterMonitorFunc = MyFilterMonitor. +// } +// beego.FilterMonitorFunc = MyFilterMonitor. var FilterMonitorFunc func(string, string, time.Duration, string, int) bool func init() { diff --git a/server/web/beego.go b/server/web/beego.go index cfe9a5dd..5c96c350 100644 --- a/server/web/beego.go +++ b/server/web/beego.go @@ -50,8 +50,9 @@ func AddAPPStartHook(hf ...hookfunc) { func Run(params ...string) { if len(params) > 0 && params[0] != "" { BeeApp.Run(params[0]) + } else { + BeeApp.Run("") } - BeeApp.Run("") } // RunWithMiddleWares Run beego application with middlewares. diff --git a/server/web/captcha/captcha.go b/server/web/captcha/captcha.go index 6d8c33b4..827c7276 100644 --- a/server/web/captcha/captcha.go +++ b/server/web/captcha/captcha.go @@ -19,32 +19,35 @@ // package controllers // // import ( -// "github.com/beego/beego/v2" -// "github.com/beego/beego/v2/client/cache" -// "github.com/beego/beego/v2/server/web/captcha" +// +// "github.com/beego/beego/v2" +// "github.com/beego/beego/v2/client/cache" +// "github.com/beego/beego/v2/server/web/captcha" +// // ) // // var cpt *captcha.Captcha // -// func init() { -// // use beego cache system store the captcha data -// store := cache.NewMemoryCache() -// cpt = captcha.NewWithFilter("/captcha/", store) -// } +// func init() { +// // use beego cache system store the captcha data +// store := cache.NewMemoryCache() +// cpt = captcha.NewWithFilter("/captcha/", store) +// } // -// type MainController struct { -// beego.Controller -// } +// type MainController struct { +// beego.Controller +// } // -// func (this *MainController) Get() { -// this.TplName = "index.tpl" -// } +// func (this *MainController) Get() { +// this.TplName = "index.tpl" +// } // -// func (this *MainController) Post() { -// this.TplName = "index.tpl" +// func (this *MainController) Post() { +// this.TplName = "index.tpl" +// +// this.Data["Success"] = cpt.VerifyReq(this.Ctx.Request) +// } // -// this.Data["Success"] = cpt.VerifyReq(this.Ctx.Request) -// } // ``` // // template usage @@ -52,8 +55,10 @@ // ``` // {{.Success}} //
-// {{create_captcha}} -// +// +// {{create_captcha}} +// +// //
// ``` package captcha diff --git a/server/web/config.go b/server/web/config.go index 006201a6..b164f0df 100644 --- a/server/web/config.go +++ b/server/web/config.go @@ -505,7 +505,7 @@ func defaultRecoverPanic(ctx *context.Context, cfg *Config) { break } logs.Critical(fmt.Sprintf("%s:%d", file, line)) - stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d", file, line)) + stack += fmt.Sprintf("%s:%d\n", file, line) } if ctx.Output.Status != 0 { @@ -629,7 +629,7 @@ func assignConfig(ac config.Configer) error { for adaptor, cfg := range BConfig.Log.Outputs { err := logs.SetLogger(adaptor, cfg) if err != nil { - fmt.Fprintln(os.Stderr, fmt.Sprintf("%s with the config %q got err:%s", adaptor, cfg, err.Error())) + fmt.Fprintf(os.Stderr, "%s with the config %q got err:%s\n", adaptor, cfg, err.Error()) return err } } diff --git a/server/web/context/context.go b/server/web/context/context.go index 8d0a3f3a..4adff2c7 100644 --- a/server/web/context/context.go +++ b/server/web/context/context.go @@ -18,7 +18,6 @@ // import "github.com/beego/beego/v2/server/web/context" // // ctx := context.Context{Request:req,ResponseWriter:rw} -// package context import ( diff --git a/server/web/context/input.go b/server/web/context/input.go index dfb14dfb..3280d68f 100644 --- a/server/web/context/input.go +++ b/server/web/context/input.go @@ -19,7 +19,6 @@ import ( "compress/gzip" "errors" "io" - "io/ioutil" "net" "net/http" "net/url" @@ -377,14 +376,14 @@ func (input *BeegoInput) CopyBody(MaxMemory int64) []byte { if err != nil { return nil } - requestbody, _ = ioutil.ReadAll(reader) + requestbody, _ = io.ReadAll(reader) } else { - requestbody, _ = ioutil.ReadAll(safe) + requestbody, _ = io.ReadAll(safe) } input.Context.Request.Body.Close() bf := bytes.NewBuffer(requestbody) - input.Context.Request.Body = http.MaxBytesReader(input.Context.ResponseWriter, ioutil.NopCloser(bf), MaxMemory) + input.Context.Request.Body = http.MaxBytesReader(input.Context.ResponseWriter, io.NopCloser(bf), MaxMemory) input.RequestBody = requestbody return requestbody } diff --git a/server/web/controller.go b/server/web/controller.go index 90cc2dd3..68b1fc64 100644 --- a/server/web/controller.go +++ b/server/web/controller.go @@ -635,31 +635,33 @@ func (c *Controller) GetFile(key string) (multipart.File, *multipart.FileHeader, // GetFiles return multi-upload files // files, err:=c.GetFiles("myfiles") +// // if err != nil { // http.Error(w, err.Error(), http.StatusNoContent) // return // } -// for i, _ := range files { -// //for each fileheader, get a handle to the actual file -// file, err := files[i].Open() -// defer file.Close() -// if err != nil { -// http.Error(w, err.Error(), http.StatusInternalServerError) -// return +// +// for i, _ := range files { +// //for each fileheader, get a handle to the actual file +// file, err := files[i].Open() +// defer file.Close() +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } +// //create destination file making sure the path is writeable. +// dst, err := os.Create("upload/" + files[i].Filename) +// defer dst.Close() +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } +// //copy the uploaded file to the destination file +// if _, err := io.Copy(dst, file); err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } // } -// //create destination file making sure the path is writeable. -// dst, err := os.Create("upload/" + files[i].Filename) -// defer dst.Close() -// if err != nil { -// http.Error(w, err.Error(), http.StatusInternalServerError) -// return -// } -// //copy the uploaded file to the destination file -// if _, err := io.Copy(dst, file); err != nil { -// http.Error(w, err.Error(), http.StatusInternalServerError) -// return -// } -// } func (c *Controller) GetFiles(key string) ([]*multipart.FileHeader, error) { if files, ok := c.Ctx.Request.MultipartForm.File[key]; ok { return files, nil diff --git a/server/web/controller_test.go b/server/web/controller_test.go index faf9ac98..fe584686 100644 --- a/server/web/controller_test.go +++ b/server/web/controller_test.go @@ -17,7 +17,6 @@ package web import ( "bytes" "io" - "io/ioutil" "math" "mime/multipart" "net/http" @@ -321,7 +320,7 @@ func testControllerRespTestCases(t *testing.T, tc respTestCase) { t.Errorf("TestResponse() failed to validate response code for %s", tc.Accept) } - bodyBytes, err := ioutil.ReadAll(response.Body) + bodyBytes, err := io.ReadAll(response.Body) if err != nil { t.Errorf("TestResponse() failed to parse response body for %s", tc.Accept) } diff --git a/server/web/doc.go b/server/web/doc.go index dd62b41a..2ea053e4 100644 --- a/server/web/doc.go +++ b/server/web/doc.go @@ -11,6 +11,5 @@ beego is inspired by Tornado, Sinatra and Flask with the added benefit of some G func main() { beego.Run() } - */ package web diff --git a/server/web/error.go b/server/web/error.go index 118585dc..da35ad8a 100644 --- a/server/web/error.go +++ b/server/web/error.go @@ -386,7 +386,8 @@ func responseError(rw http.ResponseWriter, r *http.Request, errCode int, errCont // ErrorHandler registers http.HandlerFunc to each http err code string. // usage: -// beego.ErrorHandler("404",NotFound) +// +// beego.ErrorHandler("404",NotFound) // beego.ErrorHandler("500",InternalServerError) func ErrorHandler(code string, h http.HandlerFunc) *HttpServer { ErrorMaps[code] = &errorInfo{ @@ -399,7 +400,8 @@ func ErrorHandler(code string, h http.HandlerFunc) *HttpServer { // ErrorController registers ControllerInterface to each http err code string. // usage: -// beego.ErrorController(&controllers.ErrorController{}) +// +// beego.ErrorController(&controllers.ErrorController{}) func ErrorController(c ControllerInterface) *HttpServer { reflectVal := reflect.ValueOf(c) rt := reflectVal.Type() diff --git a/server/web/filter.go b/server/web/filter.go index 2237703d..8ada5b32 100644 --- a/server/web/filter.go +++ b/server/web/filter.go @@ -43,8 +43,8 @@ type FilterRouter struct { } // params is for: -// 1. setting the returnOnOutput value (false allows multiple filters to execute) -// 2. determining whether or not params need to be reset. +// 1. setting the returnOnOutput value (false allows multiple filters to execute) +// 2. determining whether or not params need to be reset. func newFilterRouter(pattern string, filter FilterFunc, opts ...FilterOpt) *FilterRouter { mr := &FilterRouter{ tree: NewTree(), diff --git a/server/web/filter/apiauth/apiauth.go b/server/web/filter/apiauth/apiauth.go index 55a914a2..104d1770 100644 --- a/server/web/filter/apiauth/apiauth.go +++ b/server/web/filter/apiauth/apiauth.go @@ -15,6 +15,7 @@ // Package apiauth provides handlers to enable apiauth support. // // Simple Usage: +// // import( // "github.com/beego/beego/v2" // "github.com/beego/beego/v2/server/web/filter/apiauth" @@ -37,11 +38,11 @@ // // Information: // -// In the request user should include these params in the query +// # In the request user should include these params in the query // // 1. appid // -// appid is assigned to the application +// appid is assigned to the application // // 2. signature // @@ -51,8 +52,7 @@ // // 3. timestamp: // -// send the request time, the format is yyyy-mm-dd HH:ii:ss -// +// send the request time, the format is yyyy-mm-dd HH:ii:ss package apiauth import ( diff --git a/server/web/filter/auth/basic.go b/server/web/filter/auth/basic.go index 403d4b2c..2881d7cf 100644 --- a/server/web/filter/auth/basic.go +++ b/server/web/filter/auth/basic.go @@ -14,6 +14,7 @@ // Package auth provides handlers to enable basic auth support. // Simple Usage: +// // import( // "github.com/beego/beego/v2" // "github.com/beego/beego/v2/server/web/filter/auth" @@ -25,7 +26,6 @@ // beego.Run() // } // -// // Advanced Usage: // // func SecretAuth(username, password string) bool { diff --git a/server/web/filter/authz/authz.go b/server/web/filter/authz/authz.go index 4ff2d6bf..7475ea6c 100644 --- a/server/web/filter/authz/authz.go +++ b/server/web/filter/authz/authz.go @@ -14,6 +14,7 @@ // Package authz provides handlers to enable ACL, RBAC, ABAC authorization support. // Simple Usage: +// // import( // "github.com/beego/beego/v2" // "github.com/beego/beego/v2/server/web/filter/authz" @@ -26,7 +27,6 @@ // beego.Run() // } // -// // Advanced Usage: // // func main(){ diff --git a/server/web/filter/cors/cors.go b/server/web/filter/cors/cors.go index f6c68ca0..4c5cb5b7 100644 --- a/server/web/filter/cors/cors.go +++ b/server/web/filter/cors/cors.go @@ -14,9 +14,11 @@ // Package cors provides handlers to enable CORS support. // Usage +// // import ( -// "github.com/beego/beego/v2" +// "github.com/beego/beego/v2" // "github.com/beego/beego/v2/server/web/filter/cors" +// // ) // // func main() { diff --git a/server/web/filter/opentracing/filter.go b/server/web/filter/opentracing/filter.go index 641136fc..552c7a4c 100644 --- a/server/web/filter/opentracing/filter.go +++ b/server/web/filter/opentracing/filter.go @@ -17,8 +17,8 @@ package opentracing import ( "context" - logKit "github.com/go-kit/kit/log" opentracingKit "github.com/go-kit/kit/tracing/opentracing" + logKit "github.com/go-kit/log" "github.com/opentracing/opentracing-go" "github.com/beego/beego/v2/server/web" diff --git a/server/web/grace/grace.go b/server/web/grace/grace.go index bad7e61d..cefc890b 100644 --- a/server/web/grace/grace.go +++ b/server/web/grace/grace.go @@ -18,28 +18,30 @@ // Usage: // // import( -// "log" -// "net/http" -// "os" // -// "github.com/beego/beego/v2/server/web/grace" +// "log" +// "net/http" +// "os" +// +// "github.com/beego/beego/v2/server/web/grace" +// // ) // -// func handler(w http.ResponseWriter, r *http.Request) { -// w.Write([]byte("WORLD!")) -// } +// func handler(w http.ResponseWriter, r *http.Request) { +// w.Write([]byte("WORLD!")) +// } // -// func main() { -// mux := http.NewServeMux() -// mux.HandleFunc("/hello", handler) +// func main() { +// mux := http.NewServeMux() +// mux.HandleFunc("/hello", handler) // -// err := grace.ListenAndServe("localhost:8080", mux) -// if err != nil { -// log.Println(err) -// } -// log.Println("Server on 8080 stopped") -// os.Exit(0) -// } +// err := grace.ListenAndServe("localhost:8080", mux) +// if err != nil { +// log.Println(err) +// } +// log.Println("Server on 8080 stopped") +// os.Exit(0) +// } package grace import ( diff --git a/server/web/grace/server.go b/server/web/grace/server.go index 982849f3..f262f03c 100644 --- a/server/web/grace/server.go +++ b/server/web/grace/server.go @@ -5,7 +5,6 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "io/ioutil" "log" "net" "net/http" @@ -194,7 +193,7 @@ func (srv *Server) ListenMutualTLS(certFile string, keyFile string, trustFile st srv.TLSConfig.Certificates[0] = cert srv.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert pool := x509.NewCertPool() - data, err := ioutil.ReadFile(trustFile) + data, err := os.ReadFile(trustFile) if err != nil { log.Println(err) return nil, err diff --git a/server/web/namespace.go b/server/web/namespace.go index 8da8a797..0a9c7e6e 100644 --- a/server/web/namespace.go +++ b/server/web/namespace.go @@ -47,12 +47,14 @@ func NewNamespace(prefix string, params ...LinkNamespace) *Namespace { // Cond set condition function // if cond return true can run this namespace, else can't // usage: -// ns.Cond(func (ctx *context.Context) bool{ -// if ctx.Input.Domain() == "api.beego.vip" { -// return true -// } -// return false -// }) +// +// ns.Cond(func (ctx *context.Context) bool{ +// if ctx.Input.Domain() == "api.beego.vip" { +// return true +// } +// return false +// }) +// // Cond as the first filter func (n *Namespace) Cond(cond namespaceCond) *Namespace { fn := func(ctx *beecontext.Context) { @@ -77,12 +79,13 @@ func (n *Namespace) Cond(cond namespaceCond) *Namespace { // action has before & after // FilterFunc // usage: -// Filter("before", func (ctx *context.Context){ -// _, ok := ctx.Input.Session("uid").(int) -// if !ok && ctx.Request.RequestURI != "/login" { -// ctx.Redirect(302, "/login") -// } -// }) +// +// Filter("before", func (ctx *context.Context){ +// _, ok := ctx.Input.Session("uid").(int) +// if !ok && ctx.Request.RequestURI != "/login" { +// ctx.Redirect(302, "/login") +// } +// }) func (n *Namespace) Filter(action string, filter ...FilterFunc) *Namespace { var a int if action == "before" { @@ -239,18 +242,20 @@ func (n *Namespace) CtrlAny(rootpath string, f interface{}) *Namespace { // usage: // ns := beego.NewNamespace(“/v1”). // Namespace( -// beego.NewNamespace("/shop"). -// Get("/:id", func(ctx *context.Context) { -// ctx.Output.Body([]byte("shopinfo")) -// }), -// beego.NewNamespace("/order"). -// Get("/:id", func(ctx *context.Context) { -// ctx.Output.Body([]byte("orderinfo")) -// }), -// beego.NewNamespace("/crm"). -// Get("/:id", func(ctx *context.Context) { -// ctx.Output.Body([]byte("crminfo")) -// }), +// +// beego.NewNamespace("/shop"). +// Get("/:id", func(ctx *context.Context) { +// ctx.Output.Body([]byte("shopinfo")) +// }), +// beego.NewNamespace("/order"). +// Get("/:id", func(ctx *context.Context) { +// ctx.Output.Body([]byte("orderinfo")) +// }), +// beego.NewNamespace("/crm"). +// Get("/:id", func(ctx *context.Context) { +// ctx.Output.Body([]byte("crminfo")) +// }), +// // ) func (n *Namespace) Namespace(ns ...*Namespace) *Namespace { for _, ni := range ns { diff --git a/server/web/server.go b/server/web/server.go index a1a56230..8c80b20e 100644 --- a/server/web/server.go +++ b/server/web/server.go @@ -18,7 +18,6 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "io/ioutil" "net" "net/http" "net/http/fcgi" @@ -257,7 +256,7 @@ func (app *HttpServer) Run(addr string, mws ...MiddleWare) { app.Cfg.Listen.HTTPSCertFile, app.Cfg.Listen.HTTPSKeyFile = "", "" } else if app.Cfg.Listen.EnableMutualHTTPS { pool := x509.NewCertPool() - data, err := ioutil.ReadFile(app.Cfg.Listen.TrustCaFile) + data, err := os.ReadFile(app.Cfg.Listen.TrustCaFile) if err != nil { logs.Info("MutualHTTPS should provide TrustCaFile") return diff --git a/server/web/session/sess_file.go b/server/web/session/sess_file.go index 14cec1d9..05d80f42 100644 --- a/server/web/session/sess_file.go +++ b/server/web/session/sess_file.go @@ -18,7 +18,7 @@ import ( "context" "errors" "fmt" - "io/ioutil" + "io" "net/http" "os" "path" @@ -167,7 +167,7 @@ func (fp *FileProvider) SessionRead(ctx context.Context, sid string) (Store, err os.Chtimes(sidPath, time.Now(), time.Now()) var kv map[interface{}]interface{} - b, err := ioutil.ReadAll(f) + b, err := io.ReadAll(f) if err != nil { return nil, err } @@ -257,7 +257,7 @@ func (fp *FileProvider) SessionRegenerate(ctx context.Context, oldsid, sid strin // 4.return FileSessionStore _, err = os.Stat(oldSidFile) if err == nil { - b, err := ioutil.ReadFile(oldSidFile) + b, err := os.ReadFile(oldSidFile) if err != nil { return nil, err } @@ -272,7 +272,7 @@ func (fp *FileProvider) SessionRegenerate(ctx context.Context, oldsid, sid strin } } - ioutil.WriteFile(newSidFile, b, 0o777) + os.WriteFile(newSidFile, b, 0o777) os.Remove(oldSidFile) os.Chtimes(newSidFile, time.Now(), time.Now()) ss := &FileSessionStore{sid: sid, values: kv} diff --git a/server/web/session/session.go b/server/web/session/session.go index 7e46bb7f..a83542ec 100644 --- a/server/web/session/session.go +++ b/server/web/session/session.go @@ -16,14 +16,15 @@ // // Usage: // import( -// "github.com/beego/beego/v2/server/web/session" +// +// "github.com/beego/beego/v2/server/web/session" +// // ) // -// func init() { -// globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid", "enableSetCookie,omitempty": true, "gclifetime":3600, "maxLifetime": 3600, "secure": false, "cookieLifeTime": 3600, "providerConfig": ""}`) -// go globalSessions.GC() -// } -// +// func init() { +// globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid", "enableSetCookie,omitempty": true, "gclifetime":3600, "maxLifetime": 3600, "secure": false, "cookieLifeTime": 3600, "providerConfig": ""}`) +// go globalSessions.GC() +// } package session import ( diff --git a/server/web/staticfile.go b/server/web/staticfile.go index 7a120f68..e99cd297 100644 --- a/server/web/staticfile.go +++ b/server/web/staticfile.go @@ -39,12 +39,12 @@ func serverStaticRouter(ctx *context.Context) { return } - forbidden, filePath, fileInfo, err := lookupFile(ctx) + fbd, filePath, fileInfo, err := lookupFile(ctx) if err == errNotStaticRequest { return } - if forbidden { + if fbd { exception("403", ctx) return } diff --git a/server/web/staticfile_test.go b/server/web/staticfile_test.go index 621b4c17..ad2df41a 100644 --- a/server/web/staticfile_test.go +++ b/server/web/staticfile_test.go @@ -6,7 +6,6 @@ import ( "compress/zlib" "fmt" "io" - "io/ioutil" "os" "path/filepath" "testing" @@ -32,7 +31,7 @@ func testOpenFile(encoding string, content []byte, t *testing.T) { func TestOpenStaticFile_1(t *testing.T) { file, _ := os.Open(licenseFile) - content, _ := ioutil.ReadAll(file) + content, _ := io.ReadAll(file) testOpenFile("", content, t) } @@ -42,7 +41,7 @@ func TestOpenStaticFileGzip_1(t *testing.T) { fileWriter, _ := gzip.NewWriterLevel(&zipBuf, gzip.BestCompression) io.Copy(fileWriter, file) fileWriter.Close() - content, _ := ioutil.ReadAll(&zipBuf) + content, _ := io.ReadAll(&zipBuf) testOpenFile("gzip", content, t) } @@ -53,7 +52,7 @@ func TestOpenStaticFileDeflate_1(t *testing.T) { fileWriter, _ := zlib.NewWriterLevel(&zipBuf, zlib.BestCompression) io.Copy(fileWriter, file) fileWriter.Close() - content, _ := ioutil.ReadAll(&zipBuf) + content, _ := io.ReadAll(&zipBuf) testOpenFile("deflate", content, t) } @@ -89,7 +88,7 @@ func assetOpenFileAndContent(sch *serveContentHolder, reader *serveContentReader t.Log("static content file size not same") t.Fail() } - bs, _ := ioutil.ReadAll(reader) + bs, _ := io.ReadAll(reader) for i, v := range content { if v != bs[i] { t.Log("content not same") diff --git a/server/web/template.go b/server/web/template.go index 715c992d..304689cb 100644 --- a/server/web/template.go +++ b/server/web/template.go @@ -19,7 +19,6 @@ import ( "fmt" "html/template" "io" - "io/ioutil" "net/http" "os" "path/filepath" @@ -250,7 +249,7 @@ func getTplDeep(root string, fs http.FileSystem, file string, parent string, t * panic("can't find template file:" + file) } defer f.Close() - data, err := ioutil.ReadAll(f) + data, err := io.ReadAll(f) if err != nil { return nil, [][]string{}, err } @@ -324,7 +323,7 @@ func _getTemplate(t0 *template.Template, root string, fs http.FileSystem, subMod logs.Trace("template file parse error, not success open file:", err) continue } - data, err = ioutil.ReadAll(f) + data, err = io.ReadAll(f) f.Close() if err != nil { logs.Trace("template file parse error, not success read file:", err) diff --git a/server/web/templatefunc.go b/server/web/templatefunc.go index 6a380761..24f28502 100644 --- a/server/web/templatefunc.go +++ b/server/web/templatefunc.go @@ -227,21 +227,21 @@ func Htmlunquote(text string) string { } // URLFor returns url string with another registered controller handler with params. -// usage: // -// URLFor(".index") -// print URLFor("index") -// router /login -// print URLFor("login") -// print URLFor("login", "next","/"") -// router /profile/:username -// print UrlFor("profile", ":username","John Doe") -// result: -// / -// /login -// /login?next=/ -// /user/John%20Doe +// usage: // +// URLFor(".index") +// print URLFor("index") +// router /login +// print URLFor("login") +// print URLFor("login", "next","/"") +// router /profile/:username +// print UrlFor("profile", ":username","John Doe") +// result: +// / +// /login +// /login?next=/ +// /user/John%20Doe func URLFor(endpoint string, values ...interface{}) string { return BeeApp.Handlers.URLFor(endpoint, values...) } @@ -564,12 +564,13 @@ func ge(arg1, arg2 interface{}) (bool, error) { // MapGet getting value from map by keys // usage: -// Data["m"] = M{ -// "a": 1, -// "1": map[string]float64{ -// "c": 4, -// }, -// } +// +// Data["m"] = M{ +// "a": 1, +// "1": map[string]float64{ +// "c": 4, +// }, +// } // // {{ map_get m "a" }} // return 1 // {{ map_get m 1 "c" }} // return 4 diff --git a/task/task.go b/task/task.go index 3678f1a2..870210ec 100644 --- a/task/task.go +++ b/task/task.go @@ -237,11 +237,16 @@ func TimeoutOption(timeout time.Duration) Option { // week:0-6(0 means Sunday) // SetCron some signals: -// *: any time -// ,:  separate signal +// +// *: any time +// ,:  separate signal +// //    -:duration -// /n : do as n times of time duration +// +// /n : do as n times of time duration +// // /////////////////////////////////////////////////////// +// // 0/30 * * * * * every 30s // 0 43 21 * * * 21:43 // 0 15 05 * * *    05:15 @@ -724,7 +729,8 @@ func getField(field string, r bounds) uint64 { } // getRange returns the bits indicated by the given expression: -// number | number "-" number [ "/" number ] +// +// number | number "-" number [ "/" number ] func getRange(expr string, r bounds) uint64 { var ( start, end, step uint diff --git a/task/task_test.go b/task/task_test.go index 1fdfd4b9..98a3a059 100644 --- a/task/task_test.go +++ b/task/task_test.go @@ -147,7 +147,7 @@ func TestTask_Run(t *testing.T) { task := func(ctx context.Context) error { cnt++ fmt.Printf("Hello, world! %d \n", cnt) - return errors.New(fmt.Sprintf("Hello, world! %d", cnt)) + return fmt.Errorf("Hello, world! %d", cnt) } tk := NewTask("taska", "0/30 * * * * *", task) for i := 0; i < 200; i++ { diff --git a/test/bindata.go b/test/bindata.go index 632f5a47..414625e3 100644 --- a/test/bindata.go +++ b/test/bindata.go @@ -198,11 +198,13 @@ var _bindata = map[string]func() (*asset, error){ // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// // then AssetDir("data") would return []string{"foo.txt", "img"} // AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("foo.txt") and AssetDir("notexist") would return an error