diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 00000000..b8db39bc --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,11 @@ +# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json +# Minimal configuration for getting started +# language: "zh-CN" +language: "en-US" +reviews: + profile: "chill" + high_level_summary: true + auto_review: + enabled: true + drafts: false + base_branches: ["master", "v4.6", "v4.5","v1.17", "auto_review"] diff --git a/.github/workflows/adoc-review.yml b/.github/workflows/adoc-review.yml new file mode 100644 index 00000000..e9c8164a --- /dev/null +++ b/.github/workflows/adoc-review.yml @@ -0,0 +1,73 @@ +name: AsciiDoc Review + +on: + push: + branches: [main, master] + paths: ['**.adoc', '**.asciidoc'] + pull_request: + branches: [main, master] + paths: ['**.adoc', '**.asciidoc'] + +jobs: + adoc-review: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2' + bundler-cache: true + + - name: Cache gems + uses: actions/cache@v3 + with: + path: ~/.gem + key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: | + ${{ runner.os }}-gems- + + - name: Install Asciidoctor + run: | + gem install asciidoctor --version '~> 2.0' + gem install asciidoctor-diagram --version '~> 2.2' + + - name: Validate AsciiDoc syntax + run: | + set -e + files=$(find . -name "*.adoc" -o -name "*.asciidoc") + if [ -n "$files" ]; then + echo "Found AsciiDoc files to validate:" + echo "$files" + echo "$files" | xargs -I {} sh -c 'echo "Validating: $1" && asciidoctor -b docbook -o /dev/null "$1"' _ {} + else + echo "No AsciiDoc files found to validate" + fi + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Install asciidoc-link-check + run: npm install --save-dev asciidoc-link-check + + - name: Create link check config + run: | + cat > .asciidoc-link-check.json << 'EOF' + { + "ignorePatterns": [ + { + "pattern": "^http://localhost" + } + ], + "timeout": "10s", + "retryOn429": true, + "retryCount": 3 + } + EOF + + - name: Check internal links + run: | + find . \( -name "*.adoc" -o -name "*.asciidoc" \) | xargs -I {} npx asciidoc-link-check -c .asciidoc-link-check.json {} \ No newline at end of file diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml deleted file mode 100644 index 8ff0446e..00000000 --- a/.github/workflows/pr-preview.yml +++ /dev/null @@ -1,166 +0,0 @@ -name: Pr preview - -on: - pull_request_target: - -jobs: - build-and-deploy: - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - deployments: write - statuses: write - - steps: - - name: Checkout Documentation Repository (ivorysql_doc) - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - path: ivorysql_doc - - - name: Fetch All Relevant Branches into Local Docs Repo - working-directory: ./ivorysql_doc - run: | - echo "Fetching all branches from origin to update local remote-tracking branches..." - git fetch origin --prune --no-tags - - echo "--- Fetched Remote-Tracking Branches ---" - git branch -r - - - name: Checkout Doc Builder Repository (doc_builder) - uses: actions/checkout@v4 - with: - repository: ${{ github.repository_owner }}/ivory-doc-builder - path: ivory-doc-builder - - - name: Install yq - run: | - sudo apt-get update -y - sudo apt-get install -y jq - sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq - sudo chmod +x /usr/bin/yq - yq --version - - - name: Modify Antora Playbooks for Local PR Build - working-directory: ./ivory-doc-builder - env: - DETECTED_VERSION: 'master' - START_PAGE_COMPONENT_NAME: "ivorysql-doc" - START_PAGE_FILE_PATH: "welcome.adoc" - run: | - PLAYBOOK_FILES=("antora-playbook-CN.yml" "antora-playbook-EN.yml") - NEW_LOCAL_URL="../ivorysql_doc" - - for PLAYBOOK_FILE in "${PLAYBOOK_FILES[@]}"; do - if [ -f "$PLAYBOOK_FILE" ]; then - echo "--- Modifying Playbook: $PLAYBOOK_FILE ---" - echo "Original content of $PLAYBOOK_FILE:" - cat "$PLAYBOOK_FILE" - echo # Newline for better readability - - yq -i ".content.sources[0].url = \"$NEW_LOCAL_URL\"" "$PLAYBOOK_FILE" - - yq -i ".content.sources[0].branches = [\"HEAD\"]" "$PLAYBOOK_FILE" - - yq -i ".content.sources[0].edit_url = false" "$PLAYBOOK_FILE" - if [[ -n "$DETECTED_VERSION" ]]; then - NEW_START_PAGE="${START_PAGE_COMPONENT_NAME}::${DETECTED_VERSION}/${START_PAGE_FILE_PATH}" - yq -i ".site.start_page = \"$NEW_START_PAGE\"" "$PLAYBOOK_FILE" - echo "Updated .site.start_page in $PLAYBOOK_FILE to: $NEW_START_PAGE" - else - echo "WARNING: DETECTED_VERSION is empty. Skipping start_page update for $PLAYBOOK_FILE." - fi - yq -i ".site.title = .site.title + \" (PR Preview)\"" "$PLAYBOOK_FILE" - echo "Modified content of $PLAYBOOK_FILE:" - cat "$PLAYBOOK_FILE" - echo "--- Finished modification for $PLAYBOOK_FILE ---" - echo # Newline - else - echo "WARNING: Playbook file $PLAYBOOK_FILE not found in $(pwd)." - fi - done - - - name: Checkout WWW Repository (www) - uses: actions/checkout@v4 - with: - repository: ${{ github.repository_owner }}/ivorysql_web - path: www_publish_target - - - name: Setup Ruby and Bundler - uses: ruby/setup-ruby@v1 - with: - ruby-version: '3.0' - - - name: Install Asciidoctor PDF and related Gems - run: | - echo "Installing Asciidoctor PDF gems..." - gem install asciidoctor-pdf --version "~>2.3.19" - gem install rouge - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '22.15' - - - name: Install Antora CLI - run: | - echo "Installing Antora packages local..." - npm install --global antora@3.1.7 @antora/lunr-extension @antora/pdf-extension @node-rs/jieba - - - name: Build English Documentation - working-directory: ./ivory-doc-builder - run: | - echo "Current directory: $(pwd)" - echo "Building English site..." - #mkdir -p ../www_publish_target/docs/en - npx antora generate --stacktrace --to-dir ../www_publish_target/docs/en antora-playbook-EN.yml - - - name: Build Chinese Documentation - working-directory: ./ivory-doc-builder - run: | - echo "Building Chinese site..." - #mkdir -p ../www_publish_target/docs/cn - npx antora generate --stacktrace --to-dir ../www_publish_target/docs/cn antora-playbook-CN.yml - - - name: Deploy to Netlify - id: netlify_deploy - uses: nwtgck/actions-netlify@v3.0 - with: - publish-dir: './www_publish_target/docs' - production-branch: test - github-token: ${{ secrets.GITHUB_TOKEN }} - deploy-message: "Deploy preview for PR #${{ github.event.number }}" - enable-pull-request-comment: false - enable-commit-comment: false - enable-commit-status: true - alias: pr-${{ github.event.number }}-doc - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - timeout-minutes: 5 - - - name: Post Custom Preview Links Comment - if: steps.netlify_deploy.outputs.deploy-url - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const baseUrl = '${{ steps.netlify_deploy.outputs.deploy-url }}'; - - const enUrl = `${baseUrl}/en`; - - const body = ` - 🚀 **IvorySQL-Docs Preview Ready** - - - **Chinese Preview:** [${baseUrl}](${baseUrl}) - - **English Preview:** [${enUrl}](${enUrl}) - `; - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body: body - }); diff --git a/CN/modules/ROOT/pages/master/6.3.5.adoc b/CN/modules/ROOT/pages/master/6.3.5.adoc new file mode 100644 index 00000000..6a41ab3c --- /dev/null +++ b/CN/modules/ROOT/pages/master/6.3.5.adoc @@ -0,0 +1,142 @@ + +:sectnums: +:sectnumlevels: 5 + + += **功能概述** + +IvorySQL提供了兼容Oracle的NLS参数功能,包含如下参数。 + +[cols="3,7"] +|==== +|*参数名称*|*功能描述* +|ivorysql.datetime_ignore_nls_mask | 表示日期格式是否忽略NLS参数影响,默认为0。 +|nls_length_semantics | 兼容Oracle的同名参数,表示char/varchar/varchar2的类型修饰符的大小单位是字节还是字符。 +|nls_date_format | 表示默认的日期格式,可以通过show命令查看,默认为‘YYYY-MM-DD’。 +|nls_timestamp_format | 兼容Oracle的同名参数,控制带时间的日期格式。 +|nls_timestamp_tz_format | 兼容Oracle的同名参数,控制带时区的日期时间格式。 +|nls_territory | 兼容Oracle的同名参数,指定数据库的默认区域。 +|nls_iso_currency | 兼容Oracle的同名参数,指定的国家和区域制定唯一的货币符号。 +|nls_currency | 兼容Oracle的同名参数,指定显示本地货币的符号,对应数字字符串格式中占位符L。 +|==== + +== 实现原理 + +=== nls_length_semantics参数 + +IvorySQL中的数据类型存在一个属性修饰符typmod,是对类型的补充说明,比如在VARCHAR(n)类型中,n就是类型修饰符。在创建或修改表的列时可以指定长度类型,例如: +``` + ivorysql=# create table t1(name varchar2(2 byte)); +``` + +对于列类型为CHAR、VARCHAR和VARCHAR2字符型的列,当没有显式指定列的长度类型时,IvorySQL使用nls_length_semantics参数的值来决定长度类型,有byte和char两种值,默认为byte。需要特别注意的是,nls_length_semantics参数的值仅影响新创建的列,对已经存在的列不会产生任何影响。 + +在语法解析文件 ora_gram.y中,存在如下代码来根据nls_length_semantics 把原本的char/varchar/varchar2类型改成oracharchar或者oracharbyte: +``` +CharacterWithLength: character '(' Iconst ')' + { + if (ORA_PARSER == compatible_db) + { + if (strcmp($1, "bpchar")) + { + if (nls_length_semantics == NLS_LENGTH_CHAR) + $1 = "oravarcharchar"; + else + $1 = "oravarcharbyte"; + } + else + { + if (nls_length_semantics == NLS_LENGTH_CHAR) + $1 = "oracharchar"; + else + $1 = "oracharbyte"; + } + + $$ = OracleSystemTypeName($1); + $$->typmods = list_make1(makeIntConst($3, @3)); + $$->location = @1; + } + else + { + ... + } + } + ; + +``` + +IvorySQL 中数据类型oracharchar和oracharbyte的修饰符输入输出函数包括: +oravarcharchartypmodout() / oravarcharbytetypmodout() / oracharbytetypmodout() / oracharchartypmodout() + +上面这些函数调用C语言实现的函数 anychar_typmodout() ,后者根据 nls_length_semantics 的值来调整输出的内容是否包含 byte/char 的说明。 + +nls_length_semantics 另一个作用是限制表中的列长度: +根据上述代码在语法解析文件 ora_gram.y中,如果原本的varchar类型被转换成了oracharchar类型,则函数oravarcharchar()会被调用,而pg_mbcharcliplen()函数计算字符长度,而不是字节长度。 +``` +Datum +oravarcharchar(PG_FUNCTION_ARGS) +{ + VarChar *source = PG_GETARG_VARCHAR_PP(0); + int32 typmod = PG_GETARG_INT32(1); + bool isExplicit = PG_GETARG_BOOL(2); + int32 len, + maxlen; + size_t maxmblen; + char *s_data; + + len = VARSIZE_ANY_EXHDR(source); + s_data = VARDATA_ANY(source); + maxlen = typmod - VARHDRSZ; + + /* No work if typmod is invalid or supplied data fits it already */ + if (maxlen < 0 || len <= maxlen) + PG_RETURN_VARCHAR_P(source); + + maxmblen = pg_mbcharcliplen(s_data, len, maxlen); + + ... +} +``` + +=== GUC参数datetime_ignore_nls_mask + +这个参数被定义为一个int值,低四位分别表示是否在相应的日期时间格式上忽略NLS参数的影响,掩码定义如下: +``` +#define ORADATE_MASK 0x01 +#define ORATIMESTAMP_MASK 0x02 +#define ORATIMESTAMPTZ_MASK 0x04 +#define ORATIMESTAMPLTZ_MASK 0x08 +``` + +在源代码中,这个GUC参数被用于下面这些函数: +oradate_in()、oratimestamp_in()、oratimestampltz_in()以及oratimestamptz_in()。 + +如果相应的掩码被设置,则调用原生PG的处理函数,否则调用兼容代码并忽视NLS格式。 + +=== GUC参数 nls_date_format/nls_timestamp_format/nls_timestamp_tz_format + +这三个GUC参数,在函数 ora_do_to_timestamp() 中做为格式字符串,对输入的字符串进行格式检查与模式识别。 +下面是其默认值,可以通过设置其值为"pg"使其失效。"pg"表示禁用NLS特定行为,恢复为PostgreSQL的默认行为。 +``` +char *nls_date_format = "YYYY-MM-DD"; +char *nls_timestamp_format = "YYYY-MM-DD HH24:MI:SS.FF6"; +char *nls_timestamp_tz_format = "YYYY-MM-DD HH24:MI:SS.FF6 TZH:TZM"; +``` + +=== GUC参数 nls_currency/nls_iso_currency/nls_territory + +目前nls_territory和nls_iso_currency支持CHINA与AMERICA两个值 + +``` +char *nls_territory = "AMERICA"; +char *nls_currency = "$"; +char *nls_iso_currency = "AMERICA"; +``` +这三个参数将在oracle兼容函数to_number()中被使用。 +[NOTE] +==== +`to_number()`函数尚未实现。 +==== + + +还是大师啊时代是 \ No newline at end of file diff --git a/CN/modules/ROOT/pages/master/6.4.adoc b/CN/modules/ROOT/pages/master/6.4.adoc index fcad85f5..3659b944 100644 --- a/CN/modules/ROOT/pages/master/6.4.adoc +++ b/CN/modules/ROOT/pages/master/6.4.adoc @@ -25,9 +25,9 @@ PostgreSQL已支持GB18030-2000版本作为客户端编码,通过扩展的方 修改pg_enc来实现可指定GB18030作为服务端编码,PostgreSQL编码框架中增加底层函数以供pg内核调用。 -设置一个全局变量is_load_gb18030_2022,默认为true,当用户指定-E选项时,在get_encoding_id中判断其设置的是否为gb18030_2022,如果是,将其字符串转为gb18030,然后将is_load_gb18030_2022 设为true,如果-E 选项为Gb18030,将其设为false。 +设置一个全局变量is_load_gb18030_2022,默认为true,当用户指定-E选项时,在get_encoding_id中判断其设置的是否为gb18030_2022,如果是, 将其字符串转为gb18030,然后将is_load_gb18030_2022 设为true,如果-E 选项为Gb18030,将其设为false。 -在适当位置判断是否要加载插件,如果是,执行load_gb18030_2022,并将ivorysql.conf中的shared_preload_library添加gb18030_2022。 +在适当位置判断是否要加载插件, 如果是,执行load_gb18030_2022,并将ivorysql.conf中的shared_preload_library添加gb18030_2022。 ``` if (encoding_name && *encoding_name) @@ -66,7 +66,7 @@ pg_gb18030_verifier(const unsigned char *s, int len):校验字节范围,拒 发送数据: 当该客户端执行 SELECT 查询时,服务端会从磁盘/内存中读取原生的 GB18030 数据,然后调用 gb18030_to_utf8 函数将其转换为 UTF-8 格式,最后再通过网络协议发送给客户端。 -新增GB18030-2022.xml数据文件,通过perl脚本解析为map文件,提供 gb18030_to_utf8() 与 utf8_to_gb18030(),优先表驱动,覆盖不到的区间通过算法映射。 +新增GB18030-2022.xml数据文件,通过perl脚本解析为map文件,提供 gb18030_to_utf8() 与 utf8_to_gb18030(),优先表驱动,覆盖不到的区间通过算法映射; ``` static inline uint32 diff --git a/EN/modules/ROOT/pages/master/6.4.adoc b/EN/modules/ROOT/pages/master/6.4.adoc index 05776583..28429cc1 100644 --- a/EN/modules/ROOT/pages/master/6.4.adoc +++ b/EN/modules/ROOT/pages/master/6.4.adoc @@ -26,7 +26,7 @@ To enable GB18030 as a server encoding, modifications are made to pg_enc, and ne A global variable, is_load_gb18030_2022, is introduced with a default value of true. When the -E option is used during initdb, the get_encoding_id function checks the specified encoding name. If the name is gb18030_2022, it is internally mapped to the gb18030 encoding ID, and the is_load_gb18030_2022 flag is set to true. If the -E option is GB18030, the flag is set to false. -At the appropriate stage in the startup process, the system checks this flag to determine if the extension should be loaded. If required, the load_gb18030_2022 function is executed, and the gb18030_2022 extension is added to the shared_preload_libraries parameter in ivorysql.conf. +At the appropriate stage in the startup process, the system checks this flag to determine if the extension should be loaded. If required, the load_gb18030_2022 function is executed, and the gb18030_2022 extension is added to the shared_preload_libraries parameter in ivorysql.conf files. ``` if (encoding_name && *encoding_name) { diff --git a/EN/modules/ROOT/pages/master/welcome.adoc b/EN/modules/ROOT/pages/master/welcome.adoc index 0df78662..351216d3 100644 --- a/EN/modules/ROOT/pages/master/welcome.adoc +++ b/EN/modules/ROOT/pages/master/welcome.adoc @@ -12,7 +12,10 @@ Go to https://www.ivorysql.org/releases-page[IvorySQL Release Page]. == About IvorySQL IvorySQL project is an open source project proposed by Highgo Software to add the Oracle compatibility features into the popular PostgreSQL database. -It is Apache licensed Open Source and always free to use. Any comments please contact support@ivorysql.org +It was Apache licensed Open Source and always free to used. Any comments please contact support@ivorysql.org == Docs Download https://docs.ivorysql.org/en/ivorysql-doc/v4.5/ivorysql.pdf[IvorySQL v4.5 pdf documentation] + + +是的 \ No newline at end of file