2025-03-05 14:31:08
This commit is contained in:
commit
4a107fd10e
47719 changed files with 16557060 additions and 0 deletions
376
.clang-format
Normal file
376
.clang-format
Normal file
|
@ -0,0 +1,376 @@
|
|||
# Copyright (c) 2016, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# We currently use clang-format version 15.
|
||||
#
|
||||
# This is the output of
|
||||
#
|
||||
# $ clang-format-10 --style=google --dump-config
|
||||
#
|
||||
# for C++ files except for changes mentioned below.
|
||||
#
|
||||
# For JavaScript files the output is generated by:
|
||||
#
|
||||
# $ clang-format-10 --assume-filename=format.js \
|
||||
# --style=google --dump-config
|
||||
#
|
||||
# We lock the style so that any newer version of clang-format will give
|
||||
# the same result; as time goes, we may update this list, requiring
|
||||
# newer versions of clang-format.
|
||||
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: Google
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: true
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Never
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
|
||||
# We declare one specific pointer style since right alignment is dominant in
|
||||
# the MySQL code base (default --style=google has DerivePointerAlignment true).
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Right
|
||||
|
||||
Standard: Latest
|
||||
|
||||
# MySQL includes frequently are not order-independent (e.g. my_config.h needs
|
||||
# to go on top). This is unfortunate, but not something we can change easily,
|
||||
# so we keep the clang-format 8 behavior of preserving blocks.
|
||||
IncludeBlocks: Preserve
|
||||
---
|
||||
Language: JavaScript
|
||||
# BasedOnStyle: Google
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '(taze:|^/[ ]*<|@see)'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: true
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 3
|
||||
NamespaceIndentation: All
|
||||
ObjCBinPackProtocolList: Never
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
75
.clang-tidy
Normal file
75
.clang-tidy
Normal file
|
@ -0,0 +1,75 @@
|
|||
# Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Checks:
|
||||
-*,
|
||||
bugprone-*,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-bugprone-narrowing-conversions,
|
||||
clang-analyzer-*,
|
||||
-clang-diagnostic-unused-function,
|
||||
cppcoreguidelines-*,
|
||||
-cppcoreguidelines-avoid-c-arrays,
|
||||
-cppcoreguidelines-avoid-magic-numbers,
|
||||
-cppcoreguidelines-avoid-non-const-global-variables,
|
||||
-cppcoreguidelines-pro-bounds-constant-array-index,
|
||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
||||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
||||
-cppcoreguidelines-pro-type-vararg,
|
||||
-cppcoreguidelines-non-private-member-variables-in-classes,
|
||||
-cppcoreguidelines-pro-type-reinterpret-cast,
|
||||
-cppcoreguidelines-narrowing-conversions,
|
||||
google-*,
|
||||
-google-readability-todo,
|
||||
-google-readability-braces-around-statements,
|
||||
-google-runtime-int,
|
||||
-google-build-using-namespace,
|
||||
misc-*,
|
||||
-misc-const-correctness,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
modernize-use-nullptr,
|
||||
llvm-*,
|
||||
-llvm-header-guard,
|
||||
-llvm-include-order,
|
||||
performance-*,
|
||||
readability-*,
|
||||
-readability-braces-around-statements,
|
||||
-readability-named-parameter,
|
||||
-readability-redundant-member-init,
|
||||
-readability-magic-numbers,
|
||||
-clang-diagnostic-error,
|
||||
|
||||
|
||||
|
||||
CheckOptions:
|
||||
- key: readability-magic-numbers.IgnoredIntegerValues
|
||||
value: "1;2;3;4;8;9;10;15;32;127;128;240;255"
|
||||
# Allow things like CHARSET_INFO cs;
|
||||
- key: readability-identifier-length.MinimumParameterNameLength
|
||||
value: 2
|
||||
- key: readability-identifier-length.MinimumVariableNameLength
|
||||
value: 2
|
||||
- key: readability-function-cognitive-complexity.Threshold
|
||||
value: 50
|
||||
|
||||
FormatStyle: "file"
|
33
.gitconfig
Normal file
33
.gitconfig
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# To automatically add this to your git config so that “git add” and
|
||||
# “git merge” automatically run clang-format, use
|
||||
#
|
||||
# git config --local include.path ../.gitconfig
|
||||
#
|
||||
[filter "codeformat"]
|
||||
clean = clang-format --assume-filename=%f --style=file
|
||||
[merge]
|
||||
renormalize = true
|
||||
|
2776
CMakeLists.txt
Normal file
2776
CMakeLists.txt
Normal file
File diff suppressed because it is too large
Load diff
18
CONTRIBUTING.md
Normal file
18
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
We welcome your code contributions. Before submitting code via a GitHub pull
|
||||
request, or by filing a bug in https://bugs.mysql.com you will need to have
|
||||
signed the Oracle Contributor Agreement, see https://oca.opensource.oracle.com
|
||||
|
||||
Only pull requests from committers that can be verified as having signed the OCA
|
||||
can be accepted.
|
||||
|
||||
Submitting a contribution
|
||||
-------------------------
|
||||
|
||||
1. Make sure you have a user account at https://bugs.mysql.com. You'll need to reference
|
||||
this user account when you submit your OCA (Oracle Contributor Agreement).
|
||||
2. Sign the Oracle OCA. You can find instructions for doing that at the OCA Page,
|
||||
at https://oca.opensource.oracle.com
|
||||
3. Validate your contribution by including tests that sufficiently cover the functionality.
|
||||
4. Verify that the entire test suite passes with your code applied.
|
||||
5. Submit your pull request via GitHub or uploading it using the contribution tab to a bug
|
||||
record in https://bugs.mysql.com (using the 'contribution' tab).
|
104
Docs/README.build
Normal file
104
Docs/README.build
Normal file
|
@ -0,0 +1,104 @@
|
|||
Copyright (c) 2003, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Build Instructions for MySQL Server
|
||||
===================================
|
||||
|
||||
The recommended way to build MySQL for developers:
|
||||
|
||||
cd <some build directory>
|
||||
cmake <path to source directory>
|
||||
make
|
||||
|
||||
This will give you a release (actually RelWithDebInfo) build,
|
||||
with compiler options taken from
|
||||
../cmake/build_configurations/compiler_options.cmake
|
||||
|
||||
Adding -DWITH_DEBUG=1 to the cmake command line gives you a debug build.
|
||||
|
||||
|
||||
Building on Windows is slightly different:
|
||||
cd <some build directory>
|
||||
cmake <path to source directory> -G <generator>
|
||||
|
||||
We only support Visual Studio as generator and only 64 bit ("Win64").
|
||||
|
||||
cmake --build . --config Debug
|
||||
or
|
||||
cmake --build . --config RelWithDebInfo
|
||||
|
||||
You can pass options to msbuild, see
|
||||
https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-command-line-reference?view=vs-2019
|
||||
|
||||
To speed up compilation, building multiple projects in parallel:
|
||||
cmake --build . --config Debug -- -m
|
||||
|
||||
To have a completely silent build:
|
||||
cmake --build . --config Debug -- -v:q
|
||||
|
||||
Or combined:
|
||||
cmake --build . --config Debug -- -m -v:q
|
||||
|
||||
|
||||
If you have special needs, you can disable the defaults by setting
|
||||
this cmake variable off: WITH_DEFAULT_COMPILER_OPTIONS
|
||||
|
||||
Building MySQL from source requires SSL headers and libraries to be
|
||||
available. The default value for the cmake variable WITH_SSL is "system".
|
||||
This means that on UNIX systems, you should install the appropriate
|
||||
OpenSSL developer package.
|
||||
|
||||
For Windows users, please see
|
||||
https://wiki.openssl.org/index.php/Binaries
|
||||
For Mac users, please see
|
||||
http://brewformulas.org/Openssl
|
||||
|
||||
You may also build OpenSSL yourself, and do
|
||||
cmake -DWITH_SSL=</path/to/custom/openssl>
|
||||
in order to build MySQL.
|
||||
===
|
||||
|
||||
It is possible to compile with Clang on Windows, which compiles faster
|
||||
and also yields faster binaries, but this is experimental and not officially
|
||||
supported. To compile, install the most recent version from
|
||||
https://github.com/llvm/llvm-project/releases
|
||||
(Clang/C2, which is Microsoft's own version of Clang, is not supported)
|
||||
|
||||
Ensure that you have ninja and cmake in your path.
|
||||
Source the appropriate vcvarsall.bat file which comes with Visual Studio,
|
||||
so that Visual Studio executables are in your PATH.
|
||||
|
||||
cmake -G Ninja -DFORCE_UNSUPPORTED_COMPILER=1
|
||||
-DCMAKE_C_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe"
|
||||
-DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe"
|
||||
-DCMAKE_LINKER="C:/Program Files/LLVM/bin/lld-link.exe"
|
||||
..
|
||||
|
||||
ninja
|
||||
|
||||
This configuration also supports ASAN (-DWITH_ASAN=1)
|
||||
Note that leak sanitizer is *not* supported.
|
||||
|
||||
|
||||
For running tests with --parallel, you may need to add --build-thread= (500 is
|
||||
a reasonable value to try).
|
1121
Docs/sp-imp-spec.txt
Normal file
1121
Docs/sp-imp-spec.txt
Normal file
File diff suppressed because it is too large
Load diff
129
Doxyfile-ignored
Normal file
129
Doxyfile-ignored
Normal file
|
@ -0,0 +1,129 @@
|
|||
# Copyright (c) 2015, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#===========================================================================
|
||||
|
||||
# All non-empty non-comment lines are regex patterns using CMake regex
|
||||
# syntax. Matching lines will be removed from the error log when writing
|
||||
# tofix-all.log. See run_doxygen.cmake for details.
|
||||
|
||||
#===========================================================================
|
||||
# MAINTAINER:
|
||||
#
|
||||
# For bugs in the MySQL source code
|
||||
#
|
||||
# File a bug for each doxygen failure seen during the build:
|
||||
# - PRODUCT = MySQL Server (8478)
|
||||
# - COMPONENT = SRDOXYGEN
|
||||
# - make sure the title contains DOXYGEN
|
||||
# and update this file with exceptions using the templates below
|
||||
#
|
||||
# For bugs in the doxygen tool
|
||||
#
|
||||
# Indicate which doxygen version is broken,
|
||||
# Indicate which doxygen version is fixed, if any,
|
||||
# Indicate the doxygen issue number, if known
|
||||
#
|
||||
#===========================================================================
|
||||
|
||||
#===========================================================================
|
||||
# << template to remove an entire directory >>
|
||||
# BUG#XXXXXXXX - TITLE
|
||||
# DATE / BUG REPORT AUTHOR
|
||||
# storage/innobase/*
|
||||
#===========================================================================
|
||||
|
||||
#===========================================================================
|
||||
# << template to remove some files >>
|
||||
# BUG#XXXXXXXX - TITLE
|
||||
# DATE / BUG REPORT AUTHOR
|
||||
# include/m_ctype.h:[0-9]+: warning:
|
||||
#===========================================================================
|
||||
|
||||
# BUG#31354781 - FIX DOXYGEN WARNINGS IN RPL CODE
|
||||
# 07-DEC-2020 Erlend Dahl
|
||||
sql/rpl_rli_pdb.h:[0-9]+: warning:
|
||||
sql/rpl_trx_tracking.h:[0-9]+: warning:
|
||||
sql/rpl_utility.h:[0-9]+: warning:
|
||||
mysql/binlog/event/binlog_event.h:[0-9]+: warning:
|
||||
mysql/binlog/event/codecs/binary.h:[0-9]+: warning:
|
||||
mysql/binlog/event/trx_boundary_parser.h:[0-9]+: warning:
|
||||
plugin/group_replication/src/applier.cc:[0-9]+: warning:
|
||||
sql/log_event.h:[0-9]+: warning:
|
||||
sql/rpl_replica.cc:[0-9]+: warning:
|
||||
sql/rpl_trx_tracking.h:[0-9]+: warning:
|
||||
sql/rpl_utility.h:[0-9]+: warning:
|
||||
#
|
||||
# BUG#32245629 - FIX DOXYGEN WARNINGS IN THE OPTIMIZER CODE
|
||||
# 07-DEC-2020 Erlend Dahl
|
||||
sql/join_optimizer/join_optimizer.cc:[0-9]+: warning:
|
||||
sql/range_optimizer/range_optimizer.cc:[0-9]+: warning:
|
||||
sql/protocol_callback.h:[0-9]+: warning:
|
||||
sql/sql_lex.h:[0-9]+: warning:
|
||||
sql/sql_optimizer.cc:[0-9]+: warning:
|
||||
sql/sql_optimizer_internal.h:[0-9]+: warning:
|
||||
sql/sql_prepare.cc:[0-9]+: warning:
|
||||
sql/sql_table.cc:[0-9]+: warning:
|
||||
sql-common/json_dom.h:[0-9]+: warning:
|
||||
sql/handler.cc:[0-9]+: warning:
|
||||
sql/handler.h:[0-9]+: warning:
|
||||
sql/item_func.h:[0-9]+: warning:
|
||||
sql/range_optimizer/index_range_scan_plan.cc:[0-9]+: warning:
|
||||
sql/range_optimizer/index_skip_scan_plan.cc:[0-9]+: warning:
|
||||
sql/range_optimizer/index_skip_scan_plan.h:[0-9]+: warning:
|
||||
sql/range_optimizer/path_helpers.h:[0-9]+: warning:
|
||||
sql/range_optimizer/range_analysis.cc:[0-9]+: warning:
|
||||
|
||||
#===========================================================================
|
||||
# 08-DEC-2020 Marc Alff
|
||||
# Doxygen bug in 1.8.18
|
||||
# Doxygen is confused by anonymous namespaces,
|
||||
# which creates a lot of "warning: no matching class member found for"
|
||||
# and "warning: no uniquely matching class member found for"
|
||||
#
|
||||
# https://github.com/doxygen/doxygen/issues/8413
|
||||
#
|
||||
sql/join_optimizer/join_optimizer.cc:.*no matching class member found for
|
||||
sql/rpl_info_dummy.cc:.*no uniquely matching class member found for
|
||||
sql/rpl_info_table.cc:.*no uniquely matching class member found for
|
||||
sql/rwlock_scoped_lock.cc:.*no uniquely matching class member found for
|
||||
sql/sql_prepare.cc:.*no uniquely matching class member found for
|
||||
sql/log_event.cc:.*no uniquely matching class member found for
|
||||
sql/log_event.cc:.*no matching class member found for
|
||||
#===========================================================================
|
||||
|
||||
#===========================================================================
|
||||
# 09-DEC-2020 Marc Alff
|
||||
# Doxygen multiline error messages.
|
||||
#
|
||||
# Doxygen can print errors in multiple lines:
|
||||
# the first line contains the file path, line number, and error message
|
||||
# subsequent lines contains additional information.
|
||||
#
|
||||
# Ignore rules are based on the first line only (with a path),
|
||||
# so that subsequent lines are silenced here from tofix-regressions.log.
|
||||
#
|
||||
# To read a full error message, read tofix-all.log.
|
||||
#
|
||||
Possible candidates:
|
||||
^[ ]+
|
||||
#===========================================================================
|
2788
Doxyfile.in
Normal file
2788
Doxyfile.in
Normal file
File diff suppressed because it is too large
Load diff
11
INSTALL
Normal file
11
INSTALL
Normal file
|
@ -0,0 +1,11 @@
|
|||
Pre-built binaries in different package formats can be found on
|
||||
|
||||
http://www.mysql.com/downloads
|
||||
|
||||
You can find information about how to install from a source distribution at
|
||||
|
||||
http://dev.mysql.com/doc/refman/8.0/en/source-installation.html
|
||||
|
||||
The MySQL 8.0 Reference Manual is available on
|
||||
|
||||
http://dev.mysql.com/doc/refman/8.0/en/
|
5
MYSQL_VERSION
Normal file
5
MYSQL_VERSION
Normal file
|
@ -0,0 +1,5 @@
|
|||
MYSQL_VERSION_MAJOR=8
|
||||
MYSQL_VERSION_MINOR=4
|
||||
MYSQL_VERSION_PATCH=4
|
||||
MYSQL_VERSION_EXTRA=
|
||||
MYSQL_VERSION_MATURITY="LTS"
|
20
README
Normal file
20
README
Normal file
|
@ -0,0 +1,20 @@
|
|||
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
|
||||
|
||||
This is a release of MySQL, an SQL database server.
|
||||
|
||||
License information can be found in the LICENSE file.
|
||||
|
||||
In test packages where this file is renamed README-test, the license
|
||||
file is renamed LICENSE-test.
|
||||
|
||||
This distribution may include materials developed by third parties.
|
||||
For license and attribution notices for these materials,
|
||||
please refer to the LICENSE file.
|
||||
|
||||
For further information on MySQL or additional documentation, visit
|
||||
http://dev.mysql.com/doc/
|
||||
|
||||
For additional downloads and the source of MySQL, visit
|
||||
http://dev.mysql.com/downloads/
|
||||
|
||||
MySQL is brought to you by the MySQL team at Oracle.
|
32
SECURITY.md
Normal file
32
SECURITY.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
Reporting security vulnerabilities
|
||||
==================================
|
||||
|
||||
Oracle values the independent security research community and believes that
|
||||
responsible disclosure of security vulnerabilities helps us ensure the security
|
||||
and privacy of all our users.
|
||||
|
||||
Please do NOT raise a GitHub Issue to report a security vulnerability. If you
|
||||
believe you have found a security vulnerability, please submit a report to
|
||||
secalert_us@oracle.com preferably with a proof of concept. Please review
|
||||
some additional information on how to report security vulnerabilities to Oracle,
|
||||
see https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html
|
||||
|
||||
We encourage people who contact Oracle Security to use email encryption using
|
||||
our encryption key, see https://www.oracle.com/security-alerts/encryptionkey.html
|
||||
|
||||
We ask that you do not use other channels or contact the project maintainers
|
||||
directly.
|
||||
|
||||
Security updates, alerts and bulletins
|
||||
--------------------------------------
|
||||
Security updates will be released on a regular cadence. Many of our projects
|
||||
will typically release security fixes in conjunction with the Oracle Critical Patch
|
||||
Update program. Additional information, including past advisories, is available on our
|
||||
security alerts page at https://www.oracle.com/security-alerts/
|
||||
|
||||
Security-related information
|
||||
----------------------------
|
||||
We will provide security related information such as a threat model, considerations
|
||||
for secure use, or any known security issues in our documentation. Please note
|
||||
that labs and sample code are intended to demonstrate a concept and may not be
|
||||
sufficiently hardened for production use.
|
315
client/CMakeLists.txt
Normal file
315
client/CMakeLists.txt
Normal file
|
@ -0,0 +1,315 @@
|
|||
# Copyright (c) 2006, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
ADD_WSHADOW_WARNING()
|
||||
|
||||
# We are not interesting in profiling clients.
|
||||
DISABLE_MISSING_PROFILE_WARNING()
|
||||
|
||||
## Subdirectory for mysql_migrate_keyring code.
|
||||
ADD_SUBDIRECTORY(migrate_keyring)
|
||||
|
||||
MYSQL_ADD_EXECUTABLE(mysql
|
||||
${CMAKE_SOURCE_DIR}/sql-common/net_ns.cc
|
||||
completion_hash.cc
|
||||
mysql.cc
|
||||
pattern_matcher.cc
|
||||
readline.cc
|
||||
client_query_attributes.cc
|
||||
multi_factor_passwordopt-vars.cc
|
||||
multi_option.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/common/user_registration.cc
|
||||
${CMAKE_SOURCE_DIR}/sql-common/sql_string.cc
|
||||
LINK_LIBRARIES mysqlclient ${EDITLINE_LIBRARY}
|
||||
)
|
||||
|
||||
MYSQL_ADD_EXECUTABLE(mysqltest
|
||||
mysqltest.cc
|
||||
mysqltest/error_names.cc
|
||||
mysqltest/expected_errors.cc
|
||||
mysqltest/expected_warnings.cc
|
||||
mysqltest/logfile.cc
|
||||
mysqltest/regular_expressions.cc
|
||||
mysqltest/secondary_engine.cc
|
||||
mysqltest/utils.cc
|
||||
client_query_attributes.cc
|
||||
|
||||
COMPONENT Test
|
||||
DEPENDENCIES GenError GenClientError
|
||||
ENABLE_EXPORTS
|
||||
LINK_LIBRARIES mysqlclient
|
||||
)
|
||||
|
||||
IF(MY_COMPILER_IS_GNU AND (WITH_LTO OR CMAKE_COMPILER_FLAG_WITH_LTO))
|
||||
TARGET_LINK_OPTIONS(mysqltest PRIVATE -Wno-error=stringop-overflow)
|
||||
ENDIF()
|
||||
|
||||
MYSQL_ADD_EXECUTABLE(mysqlcheck
|
||||
check/mysqlcheck.cc
|
||||
check/mysqlcheck_core.cc
|
||||
multi_factor_passwordopt-vars.cc
|
||||
LINK_LIBRARIES mysqlclient
|
||||
)
|
||||
MYSQL_ADD_EXECUTABLE(mysqldump
|
||||
mysqldump.cc
|
||||
multi_factor_passwordopt-vars.cc
|
||||
multi_option.cc
|
||||
LINK_LIBRARIES mysqlclient
|
||||
)
|
||||
MYSQL_ADD_EXECUTABLE(mysqlimport
|
||||
mysqlimport.cc
|
||||
multi_factor_passwordopt-vars.cc
|
||||
LINK_LIBRARIES mysqlclient
|
||||
)
|
||||
MYSQL_ADD_EXECUTABLE(mysqlshow
|
||||
mysqlshow.cc
|
||||
multi_factor_passwordopt-vars.cc
|
||||
LINK_LIBRARIES mysqlclient
|
||||
)
|
||||
|
||||
OPTION(WITH_JSON_BINLOG_LIBRARY
|
||||
"Build and install standalone json_binlog library" OFF)
|
||||
|
||||
IF(WITH_JSON_BINLOG_LIBRARY)
|
||||
UNSET(INSTALL_JSON_BINLOG_LIBRARY)
|
||||
INSTALL(FILES
|
||||
../sql-common/json_binary.h
|
||||
../sql-common/json_error_handler.h
|
||||
DESTINATION ${INSTALL_INCLUDEDIR}/sql-common
|
||||
COMPONENT Development
|
||||
)
|
||||
ELSE()
|
||||
SET(INSTALL_JSON_BINLOG_LIBRARY SKIP_INSTALL)
|
||||
ENDIF()
|
||||
|
||||
# Set library version to match server version.
|
||||
IF(WIN32)
|
||||
# Windows wants only major.minor, but our MINOR_VERSION is zero anyways:
|
||||
SET(json_binlog_VERSION "${MAJOR_VERSION}.${PATCH_VERSION}")
|
||||
ELSE()
|
||||
SET(json_binlog_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}")
|
||||
ENDIF()
|
||||
|
||||
# This is a standalone library to de-serialize json data.
|
||||
# The public interface is in ../sql/json_binary.h which provides functions
|
||||
# for parsing binary data, and converting it to Value objects.
|
||||
# There are also utility functions to convert Value objects to JSON strings.
|
||||
# We add enough source files to make it a complete standalone library,
|
||||
# which can be tested by our ordinary mtr tests for the 'mysqlbinlog' client.
|
||||
# Some detailed interface tests are found as unit tests.
|
||||
#
|
||||
# Always build it, but do not *use* it for mysqlbinlog unless
|
||||
# WITH_JSON_BINLOG_LIBRARY=ON
|
||||
ADD_SHARED_LIBRARY(json_binlog
|
||||
${CMAKE_SOURCE_DIR}/sql-common/json_binary.cc
|
||||
${CMAKE_SOURCE_DIR}/sql-common/json_dom.cc
|
||||
${CMAKE_SOURCE_DIR}/sql-common/json_path.cc
|
||||
${CMAKE_SOURCE_DIR}/sql-common/json_syntax_check.cc
|
||||
${CMAKE_SOURCE_DIR}/sql-common/sql_string.cc
|
||||
|
||||
COMPILE_DEFINITIONS DISABLE_PSI_MUTEX EXPORT_JSON_FUNCTIONS
|
||||
DEPENDENCIES GenError
|
||||
${INSTALL_JSON_BINLOG_LIBRARY}
|
||||
LINK_LIBRARIES mysys extra::rapidjson ext::zlib decimal
|
||||
LINUX_VERSION_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/json_binlog.ver"
|
||||
VERSION "${json_binlog_VERSION}"
|
||||
NO_UNDEFINED
|
||||
)
|
||||
|
||||
ADD_CONVENIENCE_LIBRARY(json_client_library
|
||||
${CMAKE_SOURCE_DIR}/sql-common/json_binary.cc
|
||||
${CMAKE_SOURCE_DIR}/sql-common/json_dom.cc
|
||||
${CMAKE_SOURCE_DIR}/sql-common/json_path.cc
|
||||
${CMAKE_SOURCE_DIR}/sql-common/json_syntax_check.cc
|
||||
${CMAKE_SOURCE_DIR}/sql-common/sql_string.cc
|
||||
|
||||
LINK_LIBRARIES ext::zlib
|
||||
COMPILE_DEFINITIONS
|
||||
DISABLE_PSI_MUTEX
|
||||
$<TARGET_PROPERTY:extra::rapidjson,INTERFACE_COMPILE_DEFINITIONS>
|
||||
SYSTEM_INCLUDE_DIRECTORIES
|
||||
$<TARGET_PROPERTY:extra::rapidjson,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
DEPENDENCIES GenError
|
||||
)
|
||||
|
||||
ADD_CONVENIENCE_LIBRARY(decimal
|
||||
${CMAKE_SOURCE_DIR}/sql-common/my_decimal.cc
|
||||
)
|
||||
|
||||
SET(JSON_BINLOG_LIBS_TO_MERGE
|
||||
json_client_library
|
||||
mysys
|
||||
mytime
|
||||
strings
|
||||
decimal
|
||||
)
|
||||
|
||||
MERGE_CONVENIENCE_LIBRARIES(json_binlog_static
|
||||
${JSON_BINLOG_LIBS_TO_MERGE}
|
||||
COMPONENT Development
|
||||
${INSTALL_JSON_BINLOG_LIBRARY}
|
||||
)
|
||||
|
||||
# This is a test executable which verifies that Json_wrapper::seek,
|
||||
# Json_dom::seek and Json_dom::parse functions are visible and can be called.
|
||||
MYSQL_ADD_EXECUTABLE(json_client_library_main
|
||||
json_client_library_main.cc
|
||||
INCLUDE_DIRECTORIES ../sql
|
||||
LINK_LIBRARIES json_client_library strings mysys decimal
|
||||
SKIP_INSTALL
|
||||
)
|
||||
|
||||
# A test executable which does nothing, except verify that symbols are visible.
|
||||
# To test standalone build:
|
||||
# cmake -DINSTALL_MYSQLTESTDIR=0 -DWITH_JSON_BINLOG_LIBRARY=1
|
||||
# make install DESTDIR=/tmp/foo
|
||||
# g++ -I/tmp/foo/usr/local/mysql/include json_binlog_main.cc
|
||||
# -L/tmp/foo/usr/local/mysql/lib -Wl,-R,/tmp/foo/usr/local/mysql/lib
|
||||
# -ljson_binlog
|
||||
MYSQL_ADD_EXECUTABLE(json_binlog_main
|
||||
json_binlog_main.cc
|
||||
INCLUDE_DIRECTORIES ../sql ../sql-common
|
||||
LINK_LIBRARIES json_binlog
|
||||
SKIP_INSTALL
|
||||
)
|
||||
|
||||
# Same test executable, linked statically.
|
||||
# To test standalone build:
|
||||
# g++ -I/tmp/foo/usr/local/mysql/include json_binlog_main.cc
|
||||
# -L/tmp/foo/usr/local/mysql/lib
|
||||
# -ljson_binlog_static -lpthread
|
||||
MYSQL_ADD_EXECUTABLE(json_binlog_main_static
|
||||
json_binlog_main.cc
|
||||
INCLUDE_DIRECTORIES ../sql ../sql-common
|
||||
LINK_LIBRARIES json_binlog_static
|
||||
SKIP_INSTALL
|
||||
)
|
||||
|
||||
MY_CHECK_CXX_COMPILER_WARNING("-Wunused-but-set-variable" HAS_WARN_FLAG)
|
||||
IF(HAS_WARN_FLAG)
|
||||
TARGET_COMPILE_OPTIONS(json_binlog_main PRIVATE "${HAS_WARN_FLAG}")
|
||||
TARGET_COMPILE_OPTIONS(json_binlog_main_static PRIVATE "${HAS_WARN_FLAG}")
|
||||
ENDIF()
|
||||
MY_CHECK_CXX_COMPILER_WARNING("-Wunused-variable" HAS_WARN_FLAG)
|
||||
IF(HAS_WARN_FLAG)
|
||||
TARGET_COMPILE_OPTIONS(json_binlog_main PRIVATE "${HAS_WARN_FLAG}")
|
||||
TARGET_COMPILE_OPTIONS(json_binlog_main_static PRIVATE "${HAS_WARN_FLAG}")
|
||||
ENDIF()
|
||||
|
||||
SET(MYSQLBINLOG_SOURCES
|
||||
mysqlbinlog.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/log_event.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/rpl_utility.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/rpl_gtid_tsid_map.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/rpl_gtid_misc.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/rpl_gtid_set.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/rpl_gtid_specification.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/rpl_tblmap.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/basic_istream.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/binlog_istream.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/binlog_reader.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/stream_cipher.cc
|
||||
${CMAKE_SOURCE_DIR}/sql/rpl_log_encryption.cc
|
||||
)
|
||||
|
||||
# The client version of log_event.cc has false positives.
|
||||
# Downgrade from error to warning:
|
||||
IF(MY_COMPILER_IS_GNU AND CMAKE_BUILD_TYPE_UPPER STREQUAL "RELWITHDEBINFO")
|
||||
ADD_COMPILE_FLAGS(${CMAKE_SOURCE_DIR}/sql/log_event.cc
|
||||
COMPILE_FLAGS
|
||||
" -Wno-error=uninitialized"
|
||||
" -Wno-error=maybe-uninitialized"
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
# duplicate explicit instantiation of 'net_field_length_checked'
|
||||
# ignored as a Microsoft extension
|
||||
IF(WIN32_CLANG)
|
||||
ADD_COMPILE_FLAGS(${CMAKE_SOURCE_DIR}/sql/log_event.cc
|
||||
COMPILE_FLAGS " -Wno-microsoft-template")
|
||||
ENDIF()
|
||||
|
||||
SET(MYSQLBINLOG_LIBRARIES
|
||||
mysql_binlog_event
|
||||
mysqlclient
|
||||
)
|
||||
|
||||
IF(WITH_JSON_BINLOG_LIBRARY)
|
||||
LIST(APPEND MYSQLBINLOG_LIBRARIES json_binlog)
|
||||
ELSE()
|
||||
LIST(APPEND MYSQLBINLOG_LIBRARIES json_binlog_static)
|
||||
ENDIF()
|
||||
|
||||
MYSQL_ADD_EXECUTABLE(mysqlbinlog
|
||||
${MYSQLBINLOG_SOURCES}
|
||||
DEPENDENCIES GenError
|
||||
LINK_LIBRARIES ${MYSQLBINLOG_LIBRARIES}
|
||||
)
|
||||
|
||||
# __builtin_strncpy specified bound depends on the length of the source argument
|
||||
# mysqlbinlog.cc:2169:22: note: length computed here
|
||||
IF((WITH_LTO OR CMAKE_COMPILER_FLAG_WITH_LTO) AND
|
||||
MY_COMPILER_IS_GNU AND
|
||||
CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 11)
|
||||
MY_TARGET_LINK_OPTIONS(mysqlbinlog "-Wno-stringop-truncation")
|
||||
ENDIF()
|
||||
|
||||
IF(WITH_JSON_BINLOG_LIBRARY)
|
||||
IF(APPLE)
|
||||
ADD_CUSTOM_COMMAND(TARGET mysqlbinlog POST_BUILD
|
||||
COMMAND install_name_tool -change
|
||||
"@rpath/$<TARGET_FILE_NAME:json_binlog>"
|
||||
"@loader_path/../lib/$<TARGET_FILE_NAME:json_binlog>"
|
||||
"$<TARGET_FILE:mysqlbinlog>"
|
||||
)
|
||||
ELSEIF(UNIX)
|
||||
ADD_INSTALL_RPATH(mysqlbinlog "\$ORIGIN/../${INSTALL_LIBDIR}")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
TARGET_COMPILE_DEFINITIONS(mysqlbinlog PRIVATE DISABLE_PSI_MUTEX)
|
||||
TARGET_INCLUDE_DIRECTORIES(mysqlbinlog PRIVATE ${CMAKE_SOURCE_DIR}/sql)
|
||||
|
||||
MYSQL_ADD_EXECUTABLE(mysqladmin
|
||||
mysqladmin.cc
|
||||
multi_factor_passwordopt-vars.cc
|
||||
LINK_LIBRARIES mysqlclient
|
||||
)
|
||||
MYSQL_ADD_EXECUTABLE(mysqlslap
|
||||
mysqlslap.cc
|
||||
multi_factor_passwordopt-vars.cc
|
||||
LINK_LIBRARIES mysqlclient
|
||||
)
|
||||
MYSQL_ADD_EXECUTABLE(mysql_config_editor
|
||||
mysql_config_editor.cc
|
||||
LINK_LIBRARIES mysqlclient
|
||||
)
|
||||
MYSQL_ADD_EXECUTABLE(mysql_secure_installation
|
||||
mysql_secure_installation.cc
|
||||
LINK_LIBRARIES mysqlclient
|
||||
)
|
||||
|
||||
# "WIN32" also covers 64 bit. "echo" is used in some files below "mysql-test/".
|
||||
IF(WIN32)
|
||||
MYSQL_ADD_EXECUTABLE(echo echo.cc)
|
||||
ENDIF(WIN32)
|
553
client/check/mysqlcheck.cc
Normal file
553
client/check/mysqlcheck.cc
Normal file
|
@ -0,0 +1,553 @@
|
|||
/*
|
||||
Copyright (c) 2001, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "client/check/mysqlcheck.h"
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "client/include/caching_sha2_passwordopt-vars.h"
|
||||
#include "client/include/client_priv.h"
|
||||
#include "client/include/sslopt-vars.h"
|
||||
#include "compression.h"
|
||||
#include "my_alloc.h"
|
||||
#include "my_dbug.h"
|
||||
#include "my_default.h"
|
||||
#include "my_inttypes.h"
|
||||
#include "my_macros.h"
|
||||
#include "mysql/service_mysql_alloc.h"
|
||||
#include "mysql/strings/m_ctype.h"
|
||||
#include "nulls.h"
|
||||
#include "print_version.h"
|
||||
#include "typelib.h"
|
||||
#include "welcome_copyright_notice.h" /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
|
||||
|
||||
using namespace Mysql::Tools::Check;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
/* Exit codes */
|
||||
|
||||
#define EX_USAGE 1
|
||||
#define EX_MYSQLERR 2
|
||||
|
||||
static MYSQL mysql_connection, *sock = nullptr;
|
||||
static bool opt_alldbs = false, opt_check_only_changed = false,
|
||||
opt_extended = false, opt_compress = false, opt_databases = false,
|
||||
opt_fast = false, opt_medium_check = false, opt_quick = false,
|
||||
opt_all_in_1 = false, opt_silent = false, opt_auto_repair = false,
|
||||
ignore_errors = false, opt_frm = false, debug_info_flag = false,
|
||||
debug_check_flag = false, opt_fix_table_names = false,
|
||||
opt_fix_db_names = false, opt_upgrade = false,
|
||||
opt_write_binlog = true;
|
||||
static uint verbose = 0, opt_mysql_port = 0;
|
||||
static uint opt_enable_cleartext_plugin = 0;
|
||||
static bool using_opt_enable_cleartext_plugin = false;
|
||||
static int my_end_arg;
|
||||
static char *opt_mysql_unix_port = nullptr;
|
||||
static char *current_user = nullptr, *current_host = nullptr;
|
||||
static const char *default_charset = nullptr;
|
||||
static char *opt_plugin_dir = nullptr, *opt_default_auth = nullptr;
|
||||
static int first_error = 0;
|
||||
static const char *opt_skip_database = "";
|
||||
static uint opt_zstd_compress_level = default_zstd_compression_level;
|
||||
static char *opt_compress_algorithm = nullptr;
|
||||
#if defined(_WIN32)
|
||||
static char *shared_memory_base_name = nullptr;
|
||||
#endif
|
||||
static uint opt_protocol = 0;
|
||||
static char *opt_bind_addr = nullptr;
|
||||
|
||||
#include "client/include/multi_factor_passwordopt-vars.h"
|
||||
|
||||
static struct my_option my_long_options[] = {
|
||||
{"all-databases", 'A',
|
||||
"Check all the databases. This is the same as --databases with all "
|
||||
"databases selected.",
|
||||
&opt_alldbs, &opt_alldbs, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"analyze", 'a', "Analyze given tables.", nullptr, nullptr, nullptr,
|
||||
GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"all-in-1", '1',
|
||||
"Instead of issuing one query for each table, use one query per database, "
|
||||
"naming all tables in the database in a comma-separated list.",
|
||||
&opt_all_in_1, &opt_all_in_1, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr,
|
||||
0, nullptr},
|
||||
{"auto-repair", OPT_AUTO_REPAIR,
|
||||
"If a checked table is corrupted, automatically fix it. Repairing will be "
|
||||
"done after all tables have been checked, if corrupted ones were found.",
|
||||
&opt_auto_repair, &opt_auto_repair, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"bind-address", 0, "IP address to bind to.", (uchar **)&opt_bind_addr,
|
||||
(uchar **)&opt_bind_addr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr,
|
||||
0, nullptr},
|
||||
{"character-sets-dir", OPT_CHARSETS_DIR,
|
||||
"Directory for character set files.", &charsets_dir, &charsets_dir,
|
||||
nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"check", 'c', "Check table for errors.", nullptr, nullptr, nullptr,
|
||||
GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"check-only-changed", 'C',
|
||||
"Check only tables that have changed since last check or haven't been "
|
||||
"closed properly.",
|
||||
nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"check-upgrade", 'g',
|
||||
"Check tables for version-dependent changes. May be used with "
|
||||
"--auto-repair to correct tables requiring version-dependent updates.",
|
||||
nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"compress", OPT_COMPRESS, "Use compression in server/client protocol.",
|
||||
&opt_compress, &opt_compress, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr,
|
||||
0, nullptr},
|
||||
{"databases", 'B',
|
||||
"Check several databases. Note the difference in usage; in this case no "
|
||||
"tables are given. All name arguments are regarded as database names.",
|
||||
&opt_databases, &opt_databases, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
#ifdef NDEBUG
|
||||
{"debug", '#', "This is a non-debug version. Catch this and exit.", nullptr,
|
||||
nullptr, nullptr, GET_DISABLED, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"debug-check", OPT_DEBUG_CHECK,
|
||||
"This is a non-debug version. Catch this and exit.", nullptr, nullptr,
|
||||
nullptr, GET_DISABLED, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"debug-info", OPT_DEBUG_INFO,
|
||||
"This is a non-debug version. Catch this and exit.", nullptr, nullptr,
|
||||
nullptr, GET_DISABLED, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#else
|
||||
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", nullptr,
|
||||
nullptr, nullptr, GET_STR, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"debug-check", OPT_DEBUG_CHECK,
|
||||
"Check memory and open file usage at exit.", &debug_check_flag,
|
||||
&debug_check_flag, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
|
||||
&debug_info_flag, &debug_info_flag, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
#endif
|
||||
{"default-character-set", OPT_DEFAULT_CHARSET,
|
||||
"Set the default character set.", &default_charset, &default_charset,
|
||||
nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"default_auth", OPT_DEFAULT_AUTH,
|
||||
"Default authentication client-side plugin to use.", &opt_default_auth,
|
||||
&opt_default_auth, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
|
||||
"Enable/disable the clear text authentication plugin.",
|
||||
&opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin, nullptr,
|
||||
GET_BOOL, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"fast", 'F', "Check only tables that haven't been closed properly.",
|
||||
&opt_fast, &opt_fast, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"force", 'f', "Continue even if we get an SQL error.", &ignore_errors,
|
||||
&ignore_errors, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"extended", 'e',
|
||||
"If you are using this option with CHECK TABLE, it will ensure that the "
|
||||
"table is 100 percent consistent, but will take a long time. If you are "
|
||||
"using this option with REPAIR TABLE, it will force using old slow repair "
|
||||
"with keycache method, instead of much faster repair by sorting.",
|
||||
&opt_extended, &opt_extended, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr,
|
||||
0, nullptr},
|
||||
{"help", '?', "Display this help message and exit.", nullptr, nullptr,
|
||||
nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"host", 'h', "Connect to host.", ¤t_host, ¤t_host, nullptr,
|
||||
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"medium-check", 'm',
|
||||
"Faster than extended-check, but only finds 99.99 percent of all errors. "
|
||||
"Should be good enough for most cases.",
|
||||
nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"write-binlog", OPT_WRITE_BINLOG,
|
||||
"Write ANALYZE, OPTIMIZE and REPAIR TABLE commands to the binary log. "
|
||||
"Use --skip-write-binlog to omit this.",
|
||||
&opt_write_binlog, &opt_write_binlog, nullptr, GET_BOOL, NO_ARG, 1, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"optimize", 'o', "Optimize table.", nullptr, nullptr, nullptr, GET_NO_ARG,
|
||||
NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#include "client/include/multi_factor_passwordopt-longopts.h"
|
||||
#ifdef _WIN32
|
||||
{"pipe", 'W', "Use named pipes to connect to server.", nullptr, nullptr,
|
||||
nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#endif
|
||||
{"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
|
||||
&opt_plugin_dir, &opt_plugin_dir, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"port", 'P',
|
||||
"Port number to use for connection or 0 for default to, in "
|
||||
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
|
||||
#if MYSQL_PORT_DEFAULT == 0
|
||||
"/etc/services, "
|
||||
#endif
|
||||
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
|
||||
&opt_mysql_port, &opt_mysql_port, nullptr, GET_UINT, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"protocol", OPT_MYSQL_PROTOCOL,
|
||||
"The protocol to use for connection (tcp, socket, pipe, memory).", nullptr,
|
||||
nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"quick", 'q',
|
||||
"If you are using this option with CHECK TABLE, it prevents the check "
|
||||
"from scanning the rows to check for wrong links. This is the fastest "
|
||||
"check. If you are using this option with REPAIR TABLE, it will try to "
|
||||
"repair only the index tree. This is the fastest repair method for a "
|
||||
"table.",
|
||||
&opt_quick, &opt_quick, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"repair", 'r',
|
||||
"Can fix almost anything except unique keys that aren't unique.", nullptr,
|
||||
nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#if defined(_WIN32)
|
||||
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
|
||||
"Base name of shared memory.", &shared_memory_base_name,
|
||||
&shared_memory_base_name, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
#endif
|
||||
{"silent", 's', "Print only error messages.", &opt_silent, &opt_silent,
|
||||
nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"skip_database", 0, "Don't process the database specified as argument",
|
||||
&opt_skip_database, &opt_skip_database, nullptr, GET_STR, REQUIRED_ARG, 0,
|
||||
0, 0, nullptr, 0, nullptr},
|
||||
{"socket", 'S', "The socket file to use for connection.",
|
||||
&opt_mysql_unix_port, &opt_mysql_unix_port, nullptr, GET_STR, REQUIRED_ARG,
|
||||
0, 0, 0, nullptr, 0, nullptr},
|
||||
#include "client/include/caching_sha2_passwordopt-longopts.h"
|
||||
#include "client/include/sslopt-longopts.h"
|
||||
|
||||
{"tables", OPT_TABLES, "Overrides option --databases (-B).", nullptr,
|
||||
nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"use-frm", OPT_FRM,
|
||||
"When used with REPAIR, get table structure from .frm file, so the table "
|
||||
"can be repaired even if .MYI header is corrupted.",
|
||||
&opt_frm, &opt_frm, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"user", 'u', "User for login if not current user.", ¤t_user,
|
||||
¤t_user, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"verbose", 'v', "Print info about the various stages.", nullptr, nullptr,
|
||||
nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"version", 'V', "Output version information and exit.", nullptr, nullptr,
|
||||
nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"compression-algorithms", 0,
|
||||
"Use compression algorithm in server/client protocol. Valid values "
|
||||
"are any combination of 'zstd','zlib','uncompressed'.",
|
||||
&opt_compress_algorithm, &opt_compress_algorithm, nullptr, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"zstd-compression-level", 0,
|
||||
"Use this compression level in the client/server protocol, in case "
|
||||
"--compression-algorithms=zstd. Valid range is between 1 and 22, "
|
||||
"inclusive. Default is 3.",
|
||||
&opt_zstd_compress_level, &opt_zstd_compress_level, nullptr, GET_UINT,
|
||||
REQUIRED_ARG, 3, 1, 22, nullptr, 0, nullptr},
|
||||
{nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
|
||||
0, nullptr, 0, nullptr}};
|
||||
|
||||
static const char *load_default_groups[] = {"mysqlcheck", "client", nullptr};
|
||||
|
||||
static void usage(void);
|
||||
static int get_options(int *argc, char ***argv, MEM_ROOT *alloc);
|
||||
static int dbConnect(char *host, char *user);
|
||||
static void dbDisconnect(char *host);
|
||||
static void DBerror(MYSQL *mysql, const string &when);
|
||||
static void safe_exit(int error);
|
||||
|
||||
static int what_to_do = 0;
|
||||
|
||||
static void usage(void) {
|
||||
print_version();
|
||||
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
|
||||
puts(
|
||||
"This program can be used to CHECK (-c, -m, -C), REPAIR (-r), ANALYZE "
|
||||
"(-a),");
|
||||
puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be");
|
||||
puts(
|
||||
"used at the same time. Not all options are supported by all storage "
|
||||
"engines.");
|
||||
puts("Please consult the MySQL manual for latest information about the");
|
||||
puts(
|
||||
"above. The options -c, -r, -a, and -o are exclusive to each other, "
|
||||
"which");
|
||||
puts("means that the last option will be used, if several was specified.\n");
|
||||
puts("The option -c will be used by default, if none was specified. You");
|
||||
puts("can change the default behavior by making a symbolic link, or");
|
||||
puts("copying this file somewhere with another name, the alternatives are:");
|
||||
puts("mysqlrepair: The default option will be -r");
|
||||
puts("mysqlanalyze: The default option will be -a");
|
||||
puts("mysqloptimize: The default option will be -o\n");
|
||||
printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
|
||||
printf("OR %s [OPTIONS] --databases DB1 [DB2 DB3...]\n", my_progname);
|
||||
printf("OR %s [OPTIONS] --all-databases\n", my_progname);
|
||||
print_defaults("my", load_default_groups);
|
||||
my_print_help(my_long_options);
|
||||
my_print_variables(my_long_options);
|
||||
} /* usage */
|
||||
|
||||
extern "C" {
|
||||
static bool get_one_option(int optid, const struct my_option *opt,
|
||||
char *argument) {
|
||||
const int orig_what_to_do = what_to_do;
|
||||
|
||||
switch (optid) {
|
||||
case 'a':
|
||||
what_to_do = DO_ANALYZE;
|
||||
break;
|
||||
case 'c':
|
||||
what_to_do = DO_CHECK;
|
||||
break;
|
||||
case 'C':
|
||||
what_to_do = DO_CHECK;
|
||||
opt_check_only_changed = true;
|
||||
break;
|
||||
case 'I':
|
||||
[[fallthrough]];
|
||||
case '?':
|
||||
usage();
|
||||
exit(0);
|
||||
case 'm':
|
||||
what_to_do = DO_CHECK;
|
||||
opt_medium_check = true;
|
||||
break;
|
||||
case 'o':
|
||||
what_to_do = DO_OPTIMIZE;
|
||||
break;
|
||||
PARSE_COMMAND_LINE_PASSWORD_OPTION;
|
||||
case 'r':
|
||||
what_to_do = DO_REPAIR;
|
||||
break;
|
||||
case 'g':
|
||||
what_to_do = DO_CHECK;
|
||||
opt_upgrade = true;
|
||||
break;
|
||||
case 'W':
|
||||
#ifdef _WIN32
|
||||
opt_protocol = MYSQL_PROTOCOL_PIPE;
|
||||
#endif
|
||||
break;
|
||||
case '#':
|
||||
DBUG_PUSH(argument ? argument : "d:t:o");
|
||||
debug_check_flag = true;
|
||||
break;
|
||||
#include "client/include/sslopt-case.h"
|
||||
|
||||
case OPT_TABLES:
|
||||
opt_databases = false;
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
case 'V':
|
||||
print_version();
|
||||
exit(0);
|
||||
case OPT_ENABLE_CLEARTEXT_PLUGIN:
|
||||
using_opt_enable_cleartext_plugin = true;
|
||||
break;
|
||||
case OPT_MYSQL_PROTOCOL:
|
||||
opt_protocol =
|
||||
find_type_or_exit(argument, &sql_protocol_typelib, opt->name);
|
||||
break;
|
||||
case OPT_COMPRESS:
|
||||
CLIENT_WARN_DEPRECATED("--compress", "--compression-algorithms");
|
||||
break;
|
||||
}
|
||||
|
||||
if (orig_what_to_do && (what_to_do != orig_what_to_do)) {
|
||||
fprintf(stderr,
|
||||
"Error: %s doesn't support multiple contradicting commands.\n",
|
||||
my_progname);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int get_options(int *argc, char ***argv, MEM_ROOT *alloc) {
|
||||
int ho_error;
|
||||
|
||||
if (*argc == 1) {
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
my_getopt_use_args_separator = true;
|
||||
if ((ho_error =
|
||||
load_defaults("my", load_default_groups, argc, argv, alloc)) ||
|
||||
(ho_error = handle_options(argc, argv, my_long_options, get_one_option)))
|
||||
exit(ho_error);
|
||||
my_getopt_use_args_separator = false;
|
||||
|
||||
if (!what_to_do) {
|
||||
const size_t pnlen = strlen(my_progname);
|
||||
|
||||
if (pnlen < 6) /* name too short */
|
||||
what_to_do = DO_CHECK;
|
||||
else if (!strcmp("repair", my_progname + pnlen - 6))
|
||||
what_to_do = DO_REPAIR;
|
||||
else if (!strcmp("analyze", my_progname + pnlen - 7))
|
||||
what_to_do = DO_ANALYZE;
|
||||
else if (!strcmp("optimize", my_progname + pnlen - 8))
|
||||
what_to_do = DO_OPTIMIZE;
|
||||
else
|
||||
what_to_do = DO_CHECK;
|
||||
}
|
||||
|
||||
/*
|
||||
If there's no --default-character-set option given with
|
||||
--fix-table-name or --fix-db-name set the default character set to
|
||||
"utf8mb4".
|
||||
*/
|
||||
if (!default_charset) {
|
||||
if (opt_fix_db_names || opt_fix_table_names)
|
||||
default_charset = "utf8mb4";
|
||||
else
|
||||
default_charset = MYSQL_AUTODETECT_CHARSET_NAME;
|
||||
}
|
||||
if (strcmp(default_charset, MYSQL_AUTODETECT_CHARSET_NAME) &&
|
||||
!get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME))) {
|
||||
printf("Unsupported character set: %s\n", default_charset);
|
||||
return 1;
|
||||
}
|
||||
if (*argc > 0 && opt_alldbs) {
|
||||
printf("You should give only options, no arguments at all, with option\n");
|
||||
printf("--all-databases. Please see %s --help for more information.\n",
|
||||
my_progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*argc < 1 && !opt_alldbs) {
|
||||
printf("You forgot to give the arguments! Please see %s --help\n",
|
||||
my_progname);
|
||||
printf("for more information.\n");
|
||||
return 1;
|
||||
}
|
||||
if (debug_info_flag) my_end_arg = MY_CHECK_ERROR | MY_GIVE_INFO;
|
||||
if (debug_check_flag) my_end_arg = MY_CHECK_ERROR;
|
||||
return (0);
|
||||
} /* get_options */
|
||||
|
||||
static int dbConnect(char *host, char *user) {
|
||||
DBUG_TRACE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
|
||||
}
|
||||
mysql_init(&mysql_connection);
|
||||
if (opt_compress) mysql_options(&mysql_connection, MYSQL_OPT_COMPRESS, NullS);
|
||||
if (opt_compress_algorithm)
|
||||
mysql_options(&mysql_connection, MYSQL_OPT_COMPRESSION_ALGORITHMS,
|
||||
opt_compress_algorithm);
|
||||
|
||||
mysql_options(&mysql_connection, MYSQL_OPT_ZSTD_COMPRESSION_LEVEL,
|
||||
&opt_zstd_compress_level);
|
||||
|
||||
if (SSL_SET_OPTIONS(&mysql_connection)) {
|
||||
fprintf(stderr, "%s", SSL_SET_OPTIONS_ERROR);
|
||||
return 1;
|
||||
}
|
||||
if (opt_protocol)
|
||||
mysql_options(&mysql_connection, MYSQL_OPT_PROTOCOL, (char *)&opt_protocol);
|
||||
if (opt_bind_addr)
|
||||
mysql_options(&mysql_connection, MYSQL_OPT_BIND, opt_bind_addr);
|
||||
#if defined(_WIN32)
|
||||
if (shared_memory_base_name)
|
||||
mysql_options(&mysql_connection, MYSQL_SHARED_MEMORY_BASE_NAME,
|
||||
shared_memory_base_name);
|
||||
#endif
|
||||
|
||||
if (opt_plugin_dir && *opt_plugin_dir)
|
||||
mysql_options(&mysql_connection, MYSQL_PLUGIN_DIR, opt_plugin_dir);
|
||||
|
||||
if (opt_default_auth && *opt_default_auth)
|
||||
mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
||||
|
||||
if (using_opt_enable_cleartext_plugin)
|
||||
mysql_options(&mysql_connection, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
|
||||
(char *)&opt_enable_cleartext_plugin);
|
||||
|
||||
mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
|
||||
mysql_options(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_RESET, nullptr);
|
||||
mysql_options4(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name",
|
||||
"mysqlcheck");
|
||||
set_server_public_key(&mysql_connection);
|
||||
set_get_server_public_key_option(&mysql_connection);
|
||||
set_password_options(&mysql_connection);
|
||||
if (!(sock =
|
||||
mysql_real_connect(&mysql_connection, host, user, nullptr, nullptr,
|
||||
opt_mysql_port, opt_mysql_unix_port, 0))) {
|
||||
DBerror(&mysql_connection, "when trying to connect");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} /* dbConnect */
|
||||
|
||||
static void dbDisconnect(char *host) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "# Disconnecting from %s...\n", host ? host : "localhost");
|
||||
mysql_close(sock);
|
||||
} /* dbDisconnect */
|
||||
|
||||
static void DBerror(MYSQL *mysql, const string &when) {
|
||||
DBUG_TRACE;
|
||||
my_printf_error(0, "Got error: %d: %s %s", MYF(0), mysql_errno(mysql),
|
||||
mysql_error(mysql), when.c_str());
|
||||
safe_exit(EX_MYSQLERR);
|
||||
} /* DBerror */
|
||||
|
||||
static void safe_exit(int error) {
|
||||
if (!first_error) first_error = error;
|
||||
if (ignore_errors) return;
|
||||
if (sock) mysql_close(sock);
|
||||
exit(error);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
MY_INIT(argv[0]);
|
||||
/*
|
||||
** Check out the args
|
||||
*/
|
||||
MEM_ROOT alloc(PSI_NOT_INSTRUMENTED, 512);
|
||||
if (get_options(&argc, &argv, &alloc)) {
|
||||
my_end(my_end_arg);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
if (dbConnect(current_host, current_user)) exit(EX_MYSQLERR);
|
||||
|
||||
// Sun Studio does not work with range constructor from char** to string.
|
||||
vector<string> conv;
|
||||
conv.reserve(argc);
|
||||
for (int i = 0; i < argc; i++) conv.push_back(argv[i]);
|
||||
|
||||
mysql_check(sock, what_to_do, opt_alldbs, opt_check_only_changed,
|
||||
opt_extended, opt_databases, opt_fast, opt_medium_check,
|
||||
opt_quick, opt_all_in_1, opt_silent, opt_auto_repair,
|
||||
ignore_errors, opt_frm, opt_fix_table_names, opt_fix_db_names,
|
||||
opt_upgrade, opt_write_binlog, verbose, opt_skip_database, conv,
|
||||
DBerror);
|
||||
|
||||
dbDisconnect(current_host);
|
||||
free_passwords();
|
||||
#if defined(_WIN32)
|
||||
my_free(shared_memory_base_name);
|
||||
#endif
|
||||
alloc.Clear();
|
||||
my_end(my_end_arg);
|
||||
return (first_error != 0);
|
||||
} /* main */
|
147
client/check/mysqlcheck.h
Normal file
147
client/check/mysqlcheck.h
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
Copyright (c) 2014, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MYSQLCHECK_INCLUDED
|
||||
#define MYSQLCHECK_INCLUDED
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "mysql.h"
|
||||
|
||||
namespace Mysql {
|
||||
namespace Tools {
|
||||
namespace Check {
|
||||
|
||||
enum operations {
|
||||
DO_CHECK = 1,
|
||||
DO_REPAIR,
|
||||
DO_ANALYZE,
|
||||
DO_OPTIMIZE,
|
||||
DO_UPGRADE
|
||||
};
|
||||
|
||||
extern void mysql_check(MYSQL *connection, int what_to_do, bool opt_alldbs,
|
||||
bool opt_check_only_changed, bool opt_extended,
|
||||
bool opt_databases, bool opt_fast,
|
||||
bool opt_medium_check, bool opt_quick,
|
||||
bool opt_all_in_1, bool opt_silent,
|
||||
bool opt_auto_repair, bool ignore_errors, bool opt_frm,
|
||||
bool opt_fix_table_names, bool opt_fix_db_names,
|
||||
bool opt_upgrade, bool opt_write_binlog,
|
||||
unsigned int verbose, std::string opt_skip_database,
|
||||
std::vector<std::string> arguments,
|
||||
void (*dberror)(MYSQL *mysql, const std::string &when));
|
||||
|
||||
/**
|
||||
This class is object wrapper to mysql_check function. It looks like
|
||||
it is implementing Abstract_program, but it is not explicitly implementing
|
||||
it now. This is to make future implementation of Abstract_program easier.
|
||||
*/
|
||||
class Program {
|
||||
public:
|
||||
/**
|
||||
Default constructor.
|
||||
*/
|
||||
Program();
|
||||
|
||||
/**
|
||||
Checks specified databases on MySQL server.
|
||||
*/
|
||||
int check_databases(MYSQL *connection,
|
||||
const std::vector<std::string> &databases);
|
||||
/**
|
||||
Checks all databases on MySQL server.
|
||||
*/
|
||||
int check_all_databases(MYSQL *connection);
|
||||
|
||||
/**
|
||||
Automatically try to fix table when upgrade is needed.
|
||||
*/
|
||||
Program *enable_auto_repair(bool enable);
|
||||
/**
|
||||
Check and upgrade tables.
|
||||
*/
|
||||
Program *enable_upgrade(bool enable);
|
||||
/**
|
||||
Turns on verbose messages.
|
||||
*/
|
||||
Program *enable_verbosity(bool enable);
|
||||
/**
|
||||
Enables logging repairing queries to binlog.
|
||||
*/
|
||||
Program *enable_writing_binlog(bool enable);
|
||||
/**
|
||||
Enables table name fixing for all encountered tables.
|
||||
*/
|
||||
Program *enable_fixing_table_names(bool enable);
|
||||
/**
|
||||
Enables database name fixing for all encountered databases.
|
||||
*/
|
||||
Program *enable_fixing_db_names(bool enable);
|
||||
/**
|
||||
Ignores all errors and don't print error messages.
|
||||
*/
|
||||
Program *set_ignore_errors(bool ignore);
|
||||
/**
|
||||
Sets a name of database to ignore during process.
|
||||
*/
|
||||
Program *set_skip_database(std::string database);
|
||||
/**
|
||||
Sets error callback to be called when error is encountered.
|
||||
*/
|
||||
Program *set_error_callback(void (*error_callback)(MYSQL *mysql,
|
||||
const std::string &when));
|
||||
|
||||
private:
|
||||
/**
|
||||
Sets mysqlcheck program operation type to perform.
|
||||
*/
|
||||
Program *set_what_to_do(int functionality);
|
||||
/**
|
||||
Starts mysqlcheck process.
|
||||
*/
|
||||
int execute(const std::vector<std::string> &positional_options);
|
||||
|
||||
int m_what_to_do;
|
||||
bool m_auto_repair;
|
||||
bool m_upgrade;
|
||||
bool m_verbose;
|
||||
bool m_ignore_errors;
|
||||
bool m_write_binlog;
|
||||
bool m_process_all_dbs;
|
||||
bool m_fix_table_names;
|
||||
bool m_fix_db_names;
|
||||
MYSQL *m_connection;
|
||||
std::string m_database_to_skip;
|
||||
void (*m_error_callback)(MYSQL *mysql, const std::string &when);
|
||||
};
|
||||
|
||||
} // namespace Check
|
||||
} // namespace Tools
|
||||
} // namespace Mysql
|
||||
|
||||
#endif
|
530
client/check/mysqlcheck_core.cc
Normal file
530
client/check/mysqlcheck_core.cc
Normal file
|
@ -0,0 +1,530 @@
|
|||
/*
|
||||
Copyright (c) 2001, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <sys/types.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "client/check/mysqlcheck.h"
|
||||
#include "client/include/client_priv.h"
|
||||
#include "m_string.h"
|
||||
#include "my_default.h"
|
||||
#include "my_inttypes.h"
|
||||
#include "mysql/strings/m_ctype.h"
|
||||
|
||||
using namespace Mysql::Tools::Check;
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
/* ALTER instead of repair. */
|
||||
#define MAX_ALTER_STR_SIZE 128 * 1024
|
||||
#define KEY_PARTITIONING_CHANGED_STR "KEY () partitioning changed"
|
||||
|
||||
static MYSQL *sock = nullptr;
|
||||
static bool opt_alldbs = false, opt_check_only_changed = false,
|
||||
opt_extended = false, opt_databases = false, opt_fast = false,
|
||||
opt_medium_check = false, opt_quick = false, opt_all_in_1 = false,
|
||||
opt_silent = false, opt_auto_repair = false, ignore_errors = false,
|
||||
opt_frm = false, opt_fix_table_names = false,
|
||||
opt_fix_db_names = false, opt_upgrade = false,
|
||||
opt_write_binlog = true;
|
||||
static uint verbose = 0;
|
||||
static string opt_skip_database;
|
||||
int what_to_do = 0;
|
||||
|
||||
void (*DBError)(MYSQL *mysql, const string &when);
|
||||
|
||||
static int first_error = 0;
|
||||
vector<string> tables4repair, tables4rebuild, alter_table_cmds;
|
||||
|
||||
static int process_all_databases();
|
||||
static int process_databases(const vector<string> &db_names);
|
||||
static int process_selected_tables(const string &db,
|
||||
const vector<string> &table_names);
|
||||
static int process_all_tables_in_db(const string &database);
|
||||
static int process_one_db(const string &database);
|
||||
static int use_db(const string &database);
|
||||
static int handle_request_for_tables(const string &tables);
|
||||
static void print_result();
|
||||
static string escape_table_name(const string &src);
|
||||
|
||||
static int process_all_databases() {
|
||||
MYSQL_ROW row;
|
||||
MYSQL_RES *tableres;
|
||||
int result = 0;
|
||||
|
||||
if (mysql_query(sock, "SHOW DATABASES") ||
|
||||
!(tableres = mysql_store_result(sock))) {
|
||||
my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s", MYF(0),
|
||||
mysql_error(sock));
|
||||
return 1;
|
||||
}
|
||||
while ((row = mysql_fetch_row(tableres))) {
|
||||
if (process_one_db(row[0])) result = 1;
|
||||
}
|
||||
mysql_free_result(tableres);
|
||||
return result;
|
||||
}
|
||||
/* process_all_databases */
|
||||
|
||||
static int process_databases(const vector<string> &db_names) {
|
||||
int result = 0;
|
||||
for (const string &db_name : db_names) {
|
||||
if (process_one_db(db_name)) result = 1;
|
||||
}
|
||||
return result;
|
||||
} /* process_databases */
|
||||
|
||||
static int process_selected_tables(const string &db,
|
||||
const vector<string> &table_names) {
|
||||
if (use_db(db)) return 1;
|
||||
|
||||
/*
|
||||
TODO (a bug): properly handle all-in-1 option:
|
||||
we should create and pass a table list to handle_request_for_tables().
|
||||
*/
|
||||
for (const string &table_name : table_names) {
|
||||
handle_request_for_tables(escape_table_name(table_name));
|
||||
}
|
||||
|
||||
return 0;
|
||||
} /* process_selected_tables */
|
||||
|
||||
static inline void escape_str(const string &src, size_t start, size_t end,
|
||||
string &res) {
|
||||
res += '`';
|
||||
for (size_t i = start; i < end; i++) {
|
||||
switch (src[i]) {
|
||||
case '`': /* Escape backtick character. */
|
||||
res += '`';
|
||||
[[fallthrough]];
|
||||
default:
|
||||
res += src[i];
|
||||
}
|
||||
}
|
||||
res += '`';
|
||||
}
|
||||
|
||||
static string escape_table_name(const string &src) {
|
||||
string res = "";
|
||||
|
||||
escape_str(src, 0, src.length(), res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static string escape_db_table_name(const string &src, size_t dot_pos) {
|
||||
string res = "";
|
||||
|
||||
/* Escape database name. */
|
||||
escape_str(src, 0, dot_pos - 1, res);
|
||||
/* Add a dot. */
|
||||
res += '.';
|
||||
/* Escape table name. */
|
||||
escape_str(src, dot_pos, src.length(), res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int process_all_tables_in_db(const string &database) {
|
||||
MYSQL_RES *res = nullptr;
|
||||
MYSQL_ROW row;
|
||||
uint num_columns;
|
||||
|
||||
if (use_db(database)) return 1;
|
||||
if ((mysql_query(sock, "SHOW /*!50002 FULL*/ TABLES") &&
|
||||
mysql_query(sock, "SHOW TABLES")) ||
|
||||
!(res = mysql_store_result(sock))) {
|
||||
my_printf_error(0, "Error: Couldn't get table list for database %s: %s",
|
||||
MYF(0), database.c_str(), mysql_error(sock));
|
||||
return 1;
|
||||
}
|
||||
|
||||
num_columns = mysql_num_fields(res);
|
||||
|
||||
vector<string> table_names;
|
||||
|
||||
while ((row = mysql_fetch_row(res))) {
|
||||
/* Skip views if we don't perform renaming. */
|
||||
if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0)) continue;
|
||||
|
||||
table_names.push_back(row[0]);
|
||||
}
|
||||
mysql_free_result(res);
|
||||
|
||||
process_selected_tables(database, table_names);
|
||||
return 0;
|
||||
} /* process_all_tables_in_db */
|
||||
|
||||
static int run_query(const string &query) {
|
||||
if (mysql_query(sock, query.c_str())) {
|
||||
fprintf(stderr, "Failed to run query \"%s\"\n", query.c_str());
|
||||
fprintf(stderr, "Error: %s\n", mysql_error(sock));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rebuild_table(const string &name) {
|
||||
int rc = 0;
|
||||
string query = "ALTER TABLE " + name + " FORCE";
|
||||
if (mysql_real_query(sock, query.c_str(), (ulong)query.length())) {
|
||||
fprintf(stderr, "Failed to %s\n", query.c_str());
|
||||
fprintf(stderr, "Error: %s\n", mysql_error(sock));
|
||||
rc = 1;
|
||||
} else
|
||||
printf("%s\nRunning : %s\nstatus : OK\n", name.c_str(), query.c_str());
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int process_one_db(const string &database) {
|
||||
if (opt_skip_database.length() > 0 && opt_alldbs &&
|
||||
database == opt_skip_database)
|
||||
return 0;
|
||||
|
||||
return process_all_tables_in_db(database);
|
||||
}
|
||||
|
||||
static int use_db(const string &database) {
|
||||
if (mysql_get_server_version(sock) >= FIRST_INFORMATION_SCHEMA_VERSION &&
|
||||
!my_strcasecmp(&my_charset_latin1, database.c_str(),
|
||||
INFORMATION_SCHEMA_DB_NAME))
|
||||
return 1;
|
||||
if (mysql_get_server_version(sock) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
|
||||
!my_strcasecmp(&my_charset_latin1, database.c_str(),
|
||||
PERFORMANCE_SCHEMA_DB_NAME))
|
||||
return 1;
|
||||
if (mysql_select_db(sock, database.c_str())) {
|
||||
DBError(sock, "when selecting the database");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} /* use_db */
|
||||
|
||||
static int disable_binlog() { return run_query("SET SQL_LOG_BIN=0"); }
|
||||
|
||||
static int handle_request_for_tables(const string &tables) {
|
||||
string operation, options;
|
||||
|
||||
switch (what_to_do) {
|
||||
case DO_CHECK:
|
||||
operation = "CHECK";
|
||||
if (opt_quick) options += " QUICK";
|
||||
if (opt_fast) options += " FAST";
|
||||
if (opt_medium_check) options += " MEDIUM"; /* Default */
|
||||
if (opt_extended) options += " EXTENDED";
|
||||
if (opt_check_only_changed) options += " CHANGED";
|
||||
if (opt_upgrade) options += " FOR UPGRADE";
|
||||
break;
|
||||
case DO_REPAIR:
|
||||
operation = (opt_write_binlog) ? "REPAIR" : "REPAIR NO_WRITE_TO_BINLOG";
|
||||
if (opt_quick) options += " QUICK";
|
||||
if (opt_extended) options += " EXTENDED";
|
||||
if (opt_frm) options += " USE_FRM";
|
||||
break;
|
||||
case DO_ANALYZE:
|
||||
operation = (opt_write_binlog) ? "ANALYZE" : "ANALYZE NO_WRITE_TO_BINLOG";
|
||||
break;
|
||||
case DO_OPTIMIZE:
|
||||
operation =
|
||||
(opt_write_binlog) ? "OPTIMIZE" : "OPTIMIZE NO_WRITE_TO_BINLOG";
|
||||
break;
|
||||
}
|
||||
|
||||
string query = operation + " TABLE " + tables + " " + options;
|
||||
|
||||
if (mysql_real_query(sock, query.c_str(), (ulong)query.length())) {
|
||||
DBError(sock,
|
||||
"when executing '" + operation + " TABLE ... " + options + "'");
|
||||
return 1;
|
||||
}
|
||||
print_result();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_result() {
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
char prev[NAME_LEN * 3 + 2];
|
||||
char prev_alter[MAX_ALTER_STR_SIZE];
|
||||
size_t dot_pos;
|
||||
bool found_error = false, table_rebuild = false;
|
||||
|
||||
res = mysql_use_result(sock);
|
||||
dot_pos = strlen(sock->db) + 1;
|
||||
|
||||
prev[0] = '\0';
|
||||
prev_alter[0] = 0;
|
||||
|
||||
while ((row = mysql_fetch_row(res))) {
|
||||
const int changed = strcmp(prev, row[0]);
|
||||
const bool status = !strcmp(row[2], "status");
|
||||
|
||||
if (status) {
|
||||
/*
|
||||
if there was an error with the table, we have --auto-repair set,
|
||||
and this isn't a repair op, then add the table to the tables4repair
|
||||
list
|
||||
*/
|
||||
if (found_error && opt_auto_repair && what_to_do != DO_REPAIR &&
|
||||
strcmp(row[3], "OK")) {
|
||||
if (table_rebuild) {
|
||||
if (prev_alter[0])
|
||||
alter_table_cmds.push_back(prev_alter);
|
||||
else
|
||||
tables4rebuild.push_back(escape_db_table_name(prev, dot_pos));
|
||||
} else {
|
||||
tables4repair.push_back(escape_db_table_name(prev, dot_pos));
|
||||
}
|
||||
}
|
||||
found_error = false;
|
||||
table_rebuild = false;
|
||||
prev_alter[0] = 0;
|
||||
if (opt_silent) continue;
|
||||
}
|
||||
if (status && changed)
|
||||
printf("%-50s %s", row[0], row[3]);
|
||||
else if (!status && changed) {
|
||||
if (opt_auto_repair && what_to_do != DO_REPAIR) {
|
||||
printf("%-50s To be repaired, cause follows:\nServer issued %-9s: %s",
|
||||
row[0], row[2], row[3]);
|
||||
} else {
|
||||
printf("%s\n%-9s: %s", row[0], row[2], row[3]);
|
||||
}
|
||||
if (opt_auto_repair && strcmp(row[2], "note")) {
|
||||
const char *alter_txt = strstr(row[3], "ALTER TABLE");
|
||||
found_error = true;
|
||||
if (alter_txt) {
|
||||
table_rebuild = true;
|
||||
if (!strncmp(row[3], KEY_PARTITIONING_CHANGED_STR,
|
||||
strlen(KEY_PARTITIONING_CHANGED_STR)) &&
|
||||
strstr(alter_txt, "PARTITION BY")) {
|
||||
if (strlen(alter_txt) >= MAX_ALTER_STR_SIZE) {
|
||||
printf(
|
||||
"Error: Alter command too long (>= %d),"
|
||||
" please do \"%s\" or dump/reload to fix it!\n",
|
||||
MAX_ALTER_STR_SIZE, alter_txt);
|
||||
table_rebuild = false;
|
||||
prev_alter[0] = 0;
|
||||
} else {
|
||||
strncpy(prev_alter, alter_txt, MAX_ALTER_STR_SIZE - 1);
|
||||
prev_alter[MAX_ALTER_STR_SIZE - 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
printf("%-9s: %s", row[2], row[3]);
|
||||
my_stpcpy(prev, row[0]);
|
||||
putchar('\n');
|
||||
}
|
||||
/* add the last table to be repaired to the list */
|
||||
if (found_error && opt_auto_repair && what_to_do != DO_REPAIR) {
|
||||
if (table_rebuild) {
|
||||
if (prev_alter[0])
|
||||
alter_table_cmds.push_back(prev_alter);
|
||||
else
|
||||
tables4rebuild.push_back(escape_db_table_name(prev, dot_pos));
|
||||
} else {
|
||||
tables4repair.push_back(escape_db_table_name(prev, dot_pos));
|
||||
}
|
||||
}
|
||||
mysql_free_result(res);
|
||||
}
|
||||
|
||||
namespace Mysql::Tools::Check {
|
||||
|
||||
void mysql_check(MYSQL *connection, int what_to_do, bool opt_alldbs,
|
||||
bool opt_check_only_changed, bool opt_extended,
|
||||
bool opt_databases, bool opt_fast, bool opt_medium_check,
|
||||
bool opt_quick, bool opt_all_in_1, bool opt_silent,
|
||||
bool opt_auto_repair, bool ignore_errors, bool opt_frm,
|
||||
bool opt_fix_table_names, bool opt_fix_db_names,
|
||||
bool opt_upgrade, bool opt_write_binlog, uint verbose,
|
||||
std::string opt_skip_database,
|
||||
std::vector<std::string> arguments,
|
||||
void (*dberror)(MYSQL *mysql, const std::string &when)) {
|
||||
::sock = connection;
|
||||
::what_to_do = what_to_do;
|
||||
::opt_alldbs = opt_alldbs;
|
||||
::opt_check_only_changed = opt_check_only_changed;
|
||||
::opt_extended = opt_extended;
|
||||
::opt_databases = opt_databases;
|
||||
::opt_fast = opt_fast;
|
||||
::opt_medium_check = opt_medium_check;
|
||||
::opt_quick = opt_quick;
|
||||
::opt_all_in_1 = opt_all_in_1;
|
||||
::opt_silent = opt_silent;
|
||||
::opt_auto_repair = opt_auto_repair;
|
||||
::ignore_errors = ignore_errors;
|
||||
::opt_frm = opt_frm;
|
||||
::opt_fix_table_names = opt_fix_table_names;
|
||||
::opt_fix_db_names = opt_fix_db_names;
|
||||
::opt_upgrade = opt_upgrade;
|
||||
::opt_write_binlog = opt_write_binlog;
|
||||
::verbose = verbose;
|
||||
::opt_skip_database = opt_skip_database;
|
||||
::DBError = dberror;
|
||||
|
||||
if (!::opt_write_binlog) {
|
||||
if (disable_binlog()) {
|
||||
first_error = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (::opt_alldbs) process_all_databases();
|
||||
/* Only one database and selected table(s) */
|
||||
else if (arguments.size() > 1 && !::opt_databases) {
|
||||
string db_name = arguments[0];
|
||||
arguments.erase(arguments.begin());
|
||||
process_selected_tables(db_name, arguments);
|
||||
}
|
||||
/* One or more databases, all tables */
|
||||
else
|
||||
process_databases(arguments);
|
||||
if (::opt_auto_repair) {
|
||||
if (!::opt_silent && !(tables4repair.empty() && tables4rebuild.empty()))
|
||||
puts("\nRepairing tables");
|
||||
::what_to_do = DO_REPAIR;
|
||||
|
||||
for (const string &table4repair : tables4repair) {
|
||||
handle_request_for_tables(table4repair);
|
||||
}
|
||||
for (const string &table4rebuild : tables4rebuild) {
|
||||
rebuild_table(table4rebuild);
|
||||
}
|
||||
for (const string &alter_table_cmd : alter_table_cmds) {
|
||||
run_query(alter_table_cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Mysql::Tools::Check
|
||||
|
||||
Program::Program()
|
||||
: m_what_to_do(0),
|
||||
m_auto_repair(false),
|
||||
m_upgrade(false),
|
||||
m_verbose(false),
|
||||
m_ignore_errors(false),
|
||||
m_write_binlog(false),
|
||||
m_process_all_dbs(false),
|
||||
m_fix_table_names(false),
|
||||
m_fix_db_names(false),
|
||||
m_connection(nullptr),
|
||||
m_error_callback(nullptr) {}
|
||||
|
||||
int Program::check_databases(MYSQL *connection,
|
||||
const vector<string> &databases) {
|
||||
this->m_connection = connection;
|
||||
this->m_process_all_dbs = false;
|
||||
return this->set_what_to_do(DO_CHECK)->execute(databases);
|
||||
}
|
||||
|
||||
int Program::check_all_databases(MYSQL *connection) {
|
||||
this->m_connection = connection;
|
||||
this->m_process_all_dbs = true;
|
||||
return this->set_what_to_do(DO_CHECK)->execute(vector<string>());
|
||||
}
|
||||
|
||||
Program *Program::enable_auto_repair(bool enable) {
|
||||
this->m_auto_repair = enable;
|
||||
return this;
|
||||
}
|
||||
|
||||
Program *Program::enable_upgrade(bool enable) {
|
||||
this->m_upgrade = enable;
|
||||
return this;
|
||||
}
|
||||
|
||||
Program *Program::enable_verbosity(bool enable) {
|
||||
this->m_verbose = enable;
|
||||
return this;
|
||||
}
|
||||
|
||||
Program *Program::enable_writing_binlog(bool enable) {
|
||||
this->m_write_binlog = enable;
|
||||
return this;
|
||||
}
|
||||
|
||||
Program *Program::enable_fixing_table_names(bool enable) {
|
||||
this->m_fix_table_names = enable;
|
||||
return this;
|
||||
}
|
||||
|
||||
Program *Program::enable_fixing_db_names(bool enable) {
|
||||
this->m_fix_db_names = enable;
|
||||
return this;
|
||||
}
|
||||
|
||||
Program *Program::set_ignore_errors(bool ignore) {
|
||||
this->m_ignore_errors = ignore;
|
||||
return this;
|
||||
}
|
||||
|
||||
Program *Program::set_skip_database(string database) {
|
||||
this->m_database_to_skip = std::move(database);
|
||||
return this;
|
||||
}
|
||||
|
||||
Program *Program::set_error_callback(
|
||||
void (*error_callback)(MYSQL *mysql, const string &when)) {
|
||||
this->m_error_callback = error_callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
Program *Program::set_what_to_do(int functionality) {
|
||||
this->m_what_to_do = functionality;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// @relates Mysql::Tools::Check::Program
|
||||
int Program::execute(const vector<string> &positional_options) {
|
||||
Mysql::Tools::Check::mysql_check(
|
||||
this->m_connection, // connection
|
||||
this->m_what_to_do, // what_to_do
|
||||
this->m_process_all_dbs, // opt_alldbs
|
||||
false, // opt_check_only_changed
|
||||
false, // opt_extended
|
||||
!this->m_process_all_dbs, // opt_databases
|
||||
false, // opt_fast
|
||||
false, // opt_medium_check
|
||||
false, // opt_quick
|
||||
false, // opt_all_in_1
|
||||
false, // opt_silent
|
||||
this->m_auto_repair, // opt_auto_repair
|
||||
this->m_ignore_errors, // ignore_errors
|
||||
false, // opt_frm
|
||||
this->m_fix_table_names, // opt_fix_table_names
|
||||
this->m_fix_db_names, // opt_fix_db_names
|
||||
this->m_upgrade, // opt_upgrade
|
||||
this->m_write_binlog, // opt_write_binlog
|
||||
this->m_verbose, // verbose
|
||||
this->m_database_to_skip, positional_options, this->m_error_callback);
|
||||
return 0;
|
||||
}
|
93
client/client_query_attributes.cc
Normal file
93
client/client_query_attributes.cc
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
Copyright (c) 2020, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "client/include/client_priv.h"
|
||||
#include "my_config.h"
|
||||
#include "mysql/service_mysql_alloc.h" // my_malloc, my_strdup
|
||||
|
||||
#include "client/client_query_attributes.h"
|
||||
|
||||
client_query_attributes *global_attrs = nullptr;
|
||||
|
||||
bool client_query_attributes::push_param(const char *name, const char *value) {
|
||||
return push_param(name, strlen(name), value, strlen(value));
|
||||
}
|
||||
|
||||
bool client_query_attributes::push_param(const char *name, size_t name_length,
|
||||
const char *value,
|
||||
size_t value_length) {
|
||||
if (count >= max_count) return true;
|
||||
|
||||
/* Copy name */
|
||||
char *name_copy =
|
||||
(char *)my_malloc(PSI_NOT_INSTRUMENTED, name_length + 1, MYF(0));
|
||||
if (name_length) {
|
||||
memcpy(name_copy, name, name_length);
|
||||
}
|
||||
name_copy[name_length] = 0;
|
||||
|
||||
names[count] = name_copy;
|
||||
|
||||
/* Copy value */
|
||||
char *value_copy =
|
||||
(char *)my_malloc(PSI_NOT_INSTRUMENTED, value_length + 1, MYF(0));
|
||||
if (value_length) {
|
||||
memcpy(value_copy, value, value_length);
|
||||
}
|
||||
value_copy[value_length] = 0;
|
||||
|
||||
memset(&values[count], 0, sizeof(MYSQL_BIND));
|
||||
values[count].buffer = value_copy;
|
||||
values[count].buffer_length = value_length;
|
||||
values[count].buffer_type = MYSQL_TYPE_STRING;
|
||||
|
||||
count++;
|
||||
return false;
|
||||
}
|
||||
|
||||
int client_query_attributes::set_params(MYSQL *mysql) {
|
||||
if (count == 0) return 0;
|
||||
|
||||
const int rc = mysql_bind_param(mysql, count, values, names);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int client_query_attributes::set_params_stmt(MYSQL_STMT *stmt) {
|
||||
if (count == 0) return 0;
|
||||
|
||||
const int rc = mysql_stmt_bind_named_param(stmt, values, count, names);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void client_query_attributes::clear(MYSQL *mysql) {
|
||||
if (mysql != nullptr) mysql_bind_param(mysql, 0, nullptr, nullptr);
|
||||
while (count) {
|
||||
count--;
|
||||
my_free(const_cast<char *>(names[count]));
|
||||
my_free(values[count].buffer);
|
||||
}
|
||||
memset(&names, 0, sizeof(names));
|
||||
memset(&values, 0, sizeof(values));
|
||||
}
|
55
client/client_query_attributes.h
Normal file
55
client/client_query_attributes.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright (c) 2020, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef CLIENT_QUERY_ATTRIBUTES_H
|
||||
#define CLIENT_QUERY_ATTRIBUTES_H
|
||||
|
||||
#include "mysql.h"
|
||||
|
||||
class client_query_attributes {
|
||||
public:
|
||||
client_query_attributes() = default;
|
||||
~client_query_attributes() { clear(); }
|
||||
/* Assumes that name and value are 0 terminated. */
|
||||
bool push_param(const char *name, const char *value);
|
||||
/* Does not assumes that name and value are 0 terminated. */
|
||||
bool push_param(const char *name, size_t name_length, const char *value,
|
||||
size_t value_length);
|
||||
int set_params(MYSQL *mysql);
|
||||
int set_params_stmt(MYSQL_STMT *stmt);
|
||||
|
||||
void clear(MYSQL *mysql = nullptr);
|
||||
|
||||
private:
|
||||
/* 32 should be enough for everybody */
|
||||
static constexpr int max_count = 32;
|
||||
const char *names[max_count];
|
||||
MYSQL_BIND values[max_count];
|
||||
unsigned count{0};
|
||||
};
|
||||
|
||||
extern client_query_attributes *global_attrs;
|
||||
|
||||
#endif
|
253
client/common/user_registration.cc
Normal file
253
client/common/user_registration.cc
Normal file
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <scope_guard.h>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "client/include/user_registration.h"
|
||||
|
||||
#include "my_hostname.h"
|
||||
#include "my_inttypes.h"
|
||||
#include "my_sys.h"
|
||||
#include "mysql/service_mysql_alloc.h" // my_malloc
|
||||
#include "mysqld_error.h"
|
||||
|
||||
#define QUERY_LENGTH 2048
|
||||
#define MAX_QUERY_LENGTH 4096
|
||||
#define ENCODING_LENGTH 4
|
||||
#define CAPABILITY_BIT_LENGTH 1
|
||||
|
||||
/**
|
||||
This helper method parses --register-factor
|
||||
option values, and inserts the parsed values in list.
|
||||
|
||||
@param [in] what_factor Comma separated list of values, which specifies
|
||||
which factor requires registration.
|
||||
Valid values are "2", "3", "2,3" or "3,2"
|
||||
@param [out] factors container holding individual factors
|
||||
|
||||
@return true failed
|
||||
@return false success
|
||||
*/
|
||||
bool parse_register_option(const char *what_factor,
|
||||
std::vector<unsigned int> &factors) {
|
||||
std::string token;
|
||||
std::stringstream str(what_factor);
|
||||
while (getline(str, token, ',')) {
|
||||
unsigned int nth_factor = 0;
|
||||
try {
|
||||
nth_factor = std::stoul(token);
|
||||
} catch (std::invalid_argument &) {
|
||||
return true;
|
||||
} catch (std::out_of_range &) {
|
||||
return true;
|
||||
}
|
||||
/* nth_factor can be either 2 or 3 */
|
||||
if (nth_factor < 2 || nth_factor > 3) return true;
|
||||
factors.push_back(nth_factor);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
This helper method is used to perform device registration against a user
|
||||
account.
|
||||
|
||||
Please refer @ref sect_webauthn_info for more information.
|
||||
|
||||
@param [in] mysql_handle mysql connection handle
|
||||
@param [in] register_option Comma separated list of values, which
|
||||
specifies which factor requires registration. Valid values are "2", "3", "2,3"
|
||||
or "3,2"
|
||||
@param [out] errmsg Buffer to hold error message in case of error.
|
||||
|
||||
@return true failed
|
||||
@return false success
|
||||
*/
|
||||
bool user_device_registration(MYSQL *mysql_handle, char *register_option,
|
||||
char *errmsg) {
|
||||
char query[QUERY_LENGTH] = {0};
|
||||
char *query_ptr = nullptr;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
ulong *lengths;
|
||||
uchar *server_challenge = nullptr;
|
||||
uchar *server_challenge_response = nullptr;
|
||||
std::string client_plugin_name;
|
||||
struct st_mysql_client_plugin *plugin_handler = nullptr;
|
||||
std::stringstream err{};
|
||||
|
||||
auto print_error = [&errmsg, &mysql_handle, &err](bool print_mysql_error) {
|
||||
if (print_mysql_error) {
|
||||
sprintf(errmsg, "%s: %d (%s): %s\n", err.str().c_str(),
|
||||
mysql_errno(mysql_handle), mysql_sqlstate(mysql_handle),
|
||||
mysql_error(mysql_handle));
|
||||
} else {
|
||||
sprintf(errmsg, "%s\n", err.str().c_str());
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<unsigned int> factors;
|
||||
if (parse_register_option(register_option, factors)) {
|
||||
err << "Incorrect value specified for "
|
||||
"--register-factor option. "
|
||||
"Correct values can be '2', '3', '2,3' or '3,2'.";
|
||||
print_error(false);
|
||||
return true;
|
||||
}
|
||||
for (auto f : factors) {
|
||||
sprintf(query, "ALTER USER USER() %d FACTOR INITIATE REGISTRATION", f);
|
||||
if (mysql_real_query(mysql_handle, query, (ulong)strlen(query))) {
|
||||
err << "Initiate registration for " << f << " factor: ALTER USER failed";
|
||||
print_error(true);
|
||||
return true;
|
||||
}
|
||||
if (!(result = mysql_store_result(mysql_handle))) {
|
||||
err << "Initiate registration for " << f
|
||||
<< " factor: Cannot process result";
|
||||
print_error(true);
|
||||
return true;
|
||||
}
|
||||
if (mysql_num_rows(result) > 1) {
|
||||
err << "Initiate registration for " << f << " factor: Unexpected result";
|
||||
print_error(true);
|
||||
mysql_free_result(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
lengths = mysql_fetch_lengths(result);
|
||||
/*
|
||||
max length of challenge can be 32 (random challenge) +
|
||||
255 (relying party ID) + 255 (host name) + 32 (user name) + 4 byte for
|
||||
length encodings + 1 byte capability
|
||||
*/
|
||||
if (lengths[0] >
|
||||
(CHALLENGE_LENGTH + RELYING_PARTY_ID_LENGTH + HOSTNAME_LENGTH +
|
||||
USERNAME_LENGTH + ENCODING_LENGTH + CAPABILITY_BIT_LENGTH)) {
|
||||
err << "Initiate registration for " << f
|
||||
<< " factor: Received server challenge is corrupt. "
|
||||
"Please retry.";
|
||||
print_error(false);
|
||||
mysql_free_result(result);
|
||||
return true;
|
||||
}
|
||||
server_challenge = static_cast<uchar *>(my_malloc(
|
||||
PSI_NOT_INSTRUMENTED, lengths[0] + 1, MYF(MY_WME | MY_ZEROFILL)));
|
||||
memcpy(server_challenge, row[0], lengths[0]);
|
||||
|
||||
auto cleanup_guard = create_scope_guard([&] {
|
||||
if (server_challenge_response) {
|
||||
delete[] server_challenge_response;
|
||||
server_challenge_response = nullptr;
|
||||
}
|
||||
if (query_ptr && query_ptr != query) {
|
||||
my_free(query_ptr);
|
||||
query_ptr = nullptr;
|
||||
}
|
||||
if (server_challenge) {
|
||||
my_free(server_challenge);
|
||||
server_challenge = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
if (mysql_num_fields(result) >= 2) {
|
||||
if (!lengths[1] || !row[1]) {
|
||||
err << "Initiate registration for " << f
|
||||
<< " factor: No client plugin name received. Please retry.";
|
||||
print_error(false);
|
||||
mysql_free_result(result);
|
||||
return true;
|
||||
}
|
||||
client_plugin_name.assign(row[1], lengths[1]);
|
||||
}
|
||||
mysql_free_result(result);
|
||||
|
||||
plugin_handler =
|
||||
mysql_client_find_plugin(mysql_handle, client_plugin_name.c_str(),
|
||||
MYSQL_CLIENT_AUTHENTICATION_PLUGIN);
|
||||
/* check if client plugin is loaded */
|
||||
if (!plugin_handler) {
|
||||
err << "Initiate registration for " << f
|
||||
<< " factor: Loading client plugin '" << client_plugin_name
|
||||
<< "'failed with error";
|
||||
print_error(true);
|
||||
return true;
|
||||
}
|
||||
/* set server challenge in plugin */
|
||||
if (mysql_plugin_options(plugin_handler, "registration_challenge",
|
||||
server_challenge)) {
|
||||
err << "Finish registration for " << f
|
||||
<< " factor: Failed to set plugin options \"registration_challenge\" "
|
||||
"for plugin '"
|
||||
<< client_plugin_name << "'.";
|
||||
print_error(false);
|
||||
return true;
|
||||
}
|
||||
/* get challenge response from plugin, and release the memory */
|
||||
if (mysql_plugin_get_option(plugin_handler, "registration_response",
|
||||
&server_challenge_response)) {
|
||||
err << "Finish registration for " << f
|
||||
<< " factor: Failed to get plugin options \"registration_response\". "
|
||||
"for pugin '"
|
||||
<< client_plugin_name << "'.";
|
||||
print_error(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* execute FINISH REGISTRATION sql */
|
||||
int n = snprintf(query, sizeof(query),
|
||||
"ALTER USER USER() %d FACTOR FINISH REGISTRATION SET "
|
||||
"CHALLENGE_RESPONSE AS ",
|
||||
f);
|
||||
size_t tot_query_len =
|
||||
n + strlen(reinterpret_cast<char *>(server_challenge_response));
|
||||
if (tot_query_len >= MAX_QUERY_LENGTH) {
|
||||
err << "Finish registration for " << f
|
||||
<< " factor: registration_response length exceeds max "
|
||||
"supported length of "
|
||||
<< MAX_QUERY_LENGTH << "\n";
|
||||
print_error(false);
|
||||
return true;
|
||||
}
|
||||
if (tot_query_len >= QUERY_LENGTH) {
|
||||
/* allocate required buffer to construct query */
|
||||
query_ptr = static_cast<char *>(my_malloc(
|
||||
PSI_NOT_INSTRUMENTED, tot_query_len + 1, MYF(MY_WME | MY_ZEROFILL)));
|
||||
}
|
||||
if (query_ptr == nullptr) query_ptr = query;
|
||||
sprintf(query_ptr,
|
||||
"ALTER USER USER() %d FACTOR FINISH REGISTRATION SET "
|
||||
"CHALLENGE_RESPONSE AS '%s'",
|
||||
f, server_challenge_response);
|
||||
if (mysql_real_query(mysql_handle, query, (ulong)strlen(query))) {
|
||||
err << "Finish registration for " << f << " factor failed";
|
||||
print_error(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
209
client/completion_hash.cc
Normal file
209
client/completion_hash.cc
Normal file
|
@ -0,0 +1,209 @@
|
|||
/* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
// Hash implementation used for tab completion.
|
||||
// TODO: Use a trie or similar instead.
|
||||
|
||||
#include "client/completion_hash.h"
|
||||
|
||||
#include "m_string.h"
|
||||
#include "my_alloc.h"
|
||||
#include "my_inttypes.h"
|
||||
#include "my_sys.h"
|
||||
#include "mysql/service_mysql_alloc.h"
|
||||
|
||||
static uint hashpjw(const char *arKey, uint nKeyLength) {
|
||||
uint h = 0, g, i;
|
||||
|
||||
for (i = 0; i < nKeyLength; i++) {
|
||||
h = (h << 4) + arKey[i];
|
||||
if ((g = (h & 0xF0000000))) {
|
||||
h = h ^ (g >> 24);
|
||||
h = h ^ g;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
int completion_hash_init(HashTable *ht, uint nSize) {
|
||||
ht->arBuckets =
|
||||
(Bucket **)my_malloc(PSI_NOT_INSTRUMENTED, nSize * sizeof(Bucket *),
|
||||
MYF(MY_ZEROFILL | MY_WME));
|
||||
|
||||
if (!ht->arBuckets) {
|
||||
ht->initialized = 0;
|
||||
return FAILURE;
|
||||
}
|
||||
::new ((void *)&ht->mem_root) MEM_ROOT(PSI_NOT_INSTRUMENTED, 8192);
|
||||
ht->pHashFunction = hashpjw;
|
||||
ht->nTableSize = nSize;
|
||||
ht->initialized = 1;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int completion_hash_update(HashTable *ht, const char *arKey, uint nKeyLength,
|
||||
const char *str) {
|
||||
uint h, nIndex;
|
||||
|
||||
Bucket *p;
|
||||
|
||||
h = ht->pHashFunction(arKey, nKeyLength);
|
||||
nIndex = h % ht->nTableSize;
|
||||
|
||||
if (nKeyLength <= 0) {
|
||||
return FAILURE;
|
||||
}
|
||||
p = ht->arBuckets[nIndex];
|
||||
while (p) {
|
||||
if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
|
||||
if (!memcmp(p->arKey, arKey, nKeyLength)) {
|
||||
entry *n;
|
||||
|
||||
if (!(n = (entry *)ht->mem_root.Alloc(sizeof(entry)))) return FAILURE;
|
||||
n->pNext = p->pData;
|
||||
n->str = str;
|
||||
p->pData = n;
|
||||
p->count++;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
p = p->pNext;
|
||||
}
|
||||
|
||||
if (!(p = (Bucket *)ht->mem_root.Alloc(sizeof(Bucket)))) return FAILURE;
|
||||
|
||||
p->arKey = arKey;
|
||||
p->nKeyLength = nKeyLength;
|
||||
p->h = h;
|
||||
|
||||
if (!(p->pData = (entry *)ht->mem_root.Alloc(sizeof(entry)))) return FAILURE;
|
||||
|
||||
p->pData->str = str;
|
||||
p->pData->pNext = nullptr;
|
||||
p->count = 1;
|
||||
|
||||
p->pNext = ht->arBuckets[nIndex];
|
||||
ht->arBuckets[nIndex] = p;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static Bucket *completion_hash_find(HashTable *ht, const char *arKey,
|
||||
uint nKeyLength) {
|
||||
uint h, nIndex;
|
||||
Bucket *p;
|
||||
|
||||
h = ht->pHashFunction(arKey, nKeyLength);
|
||||
nIndex = h % ht->nTableSize;
|
||||
|
||||
p = ht->arBuckets[nIndex];
|
||||
while (p) {
|
||||
if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
|
||||
if (!memcmp(p->arKey, arKey, nKeyLength)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
p = p->pNext;
|
||||
}
|
||||
return (Bucket *)nullptr;
|
||||
}
|
||||
|
||||
int completion_hash_exists(HashTable *ht, char *arKey, uint nKeyLength) {
|
||||
uint h, nIndex;
|
||||
Bucket *p;
|
||||
|
||||
h = ht->pHashFunction(arKey, nKeyLength);
|
||||
nIndex = h % ht->nTableSize;
|
||||
|
||||
p = ht->arBuckets[nIndex];
|
||||
while (p) {
|
||||
if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
|
||||
if (!strcmp(p->arKey, arKey)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
p = p->pNext;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Bucket *find_all_matches(HashTable *ht, const char *str, uint length,
|
||||
uint *res_length) {
|
||||
Bucket *b;
|
||||
|
||||
b = completion_hash_find(ht, str, length);
|
||||
if (!b) {
|
||||
*res_length = 0;
|
||||
return (Bucket *)nullptr;
|
||||
} else {
|
||||
*res_length = length;
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
Bucket *find_longest_match(HashTable *ht, char *str, uint length,
|
||||
uint *res_length) {
|
||||
Bucket *b, *return_b;
|
||||
const char *s;
|
||||
uint count;
|
||||
uint lm;
|
||||
|
||||
b = completion_hash_find(ht, str, length);
|
||||
if (!b) {
|
||||
*res_length = 0;
|
||||
return (Bucket *)nullptr;
|
||||
}
|
||||
|
||||
count = b->count;
|
||||
lm = length;
|
||||
s = b->pData->str;
|
||||
|
||||
return_b = b;
|
||||
while (s[lm] != 0 && (b = completion_hash_find(ht, s, lm + 1))) {
|
||||
if (b->count < count) {
|
||||
*res_length = lm;
|
||||
return return_b;
|
||||
}
|
||||
return_b = b;
|
||||
lm++;
|
||||
}
|
||||
*res_length = lm;
|
||||
return return_b;
|
||||
}
|
||||
|
||||
void completion_hash_clean(HashTable *ht) {
|
||||
ht->mem_root.Clear();
|
||||
memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
|
||||
}
|
||||
|
||||
void completion_hash_free(HashTable *ht) {
|
||||
completion_hash_clean(ht);
|
||||
my_free(ht->arBuckets);
|
||||
}
|
||||
|
||||
void add_word(HashTable *ht, const char *str) {
|
||||
int i;
|
||||
const char *pos = str;
|
||||
for (i = 1; *pos; i++, pos++) completion_hash_update(ht, str, i, str);
|
||||
}
|
70
client/completion_hash.h
Normal file
70
client/completion_hash.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef _HASH_
|
||||
#define _HASH_
|
||||
|
||||
#define SUCCESS 0
|
||||
#define FAILURE 1
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "my_alloc.h"
|
||||
#include "my_sys.h"
|
||||
|
||||
typedef struct _entry {
|
||||
const char *str;
|
||||
struct _entry *pNext;
|
||||
} entry;
|
||||
|
||||
typedef struct bucket {
|
||||
uint h; /* Used for numeric indexing */
|
||||
const char *arKey;
|
||||
uint nKeyLength;
|
||||
uint count;
|
||||
entry *pData;
|
||||
struct bucket *pNext;
|
||||
} Bucket;
|
||||
|
||||
typedef struct hashtable {
|
||||
uint nTableSize;
|
||||
uint initialized;
|
||||
MEM_ROOT mem_root;
|
||||
uint (*pHashFunction)(const char *arKey, uint nKeyLength);
|
||||
Bucket **arBuckets;
|
||||
} HashTable;
|
||||
|
||||
extern int completion_hash_init(HashTable *ht, uint nSize);
|
||||
extern int completion_hash_update(HashTable *ht, const char *arKey,
|
||||
uint nKeyLength, const char *str);
|
||||
extern int hash_exists(HashTable *ht, char *arKey);
|
||||
extern Bucket *find_all_matches(HashTable *ht, const char *str, uint length,
|
||||
uint *res_length);
|
||||
extern Bucket *find_longest_match(HashTable *ht, char *str, uint length,
|
||||
uint *res_length);
|
||||
extern void add_word(HashTable *ht, const char *str);
|
||||
extern void completion_hash_clean(HashTable *ht);
|
||||
extern int completion_hash_exists(HashTable *ht, char *arKey, uint nKeyLength);
|
||||
extern void completion_hash_free(HashTable *ht);
|
||||
|
||||
#endif /* _HASH_ */
|
49
client/echo.cc
Normal file
49
client/echo.cc
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/*
|
||||
echo is a replacement for the "echo" command builtin to cmd.exe
|
||||
on Windows, to get a Unix eqvivalent behaviour when running commands
|
||||
like:
|
||||
$> echo "hello" | mysql
|
||||
|
||||
The windows "echo" would have sent "hello" to mysql while
|
||||
Unix echo will send hello without the enclosing hyphens
|
||||
|
||||
This is a very advanced high tech program so take care when
|
||||
you change it and remember to valgrind it before production
|
||||
use.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
for (i = 1; i < argc; i++) {
|
||||
fprintf(stdout, "%s", argv[i]);
|
||||
if (i < argc - 1) fprintf(stdout, " ");
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
return 0;
|
||||
}
|
29
client/include/authentication_kerberos_clientopt-case.h
Normal file
29
client/include/authentication_kerberos_clientopt-case.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#if defined(_WIN32)
|
||||
case OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE:
|
||||
opt_authentication_kerberos_client_mode =
|
||||
find_type_or_exit(argument, &client_mode_typelib, opt->name) - 1;
|
||||
break;
|
||||
#endif
|
40
client/include/authentication_kerberos_clientopt-longopts.h
Normal file
40
client/include/authentication_kerberos_clientopt-longopts.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#if defined(_WIN32)
|
||||
{"plugin_authentication_kerberos_client_mode",
|
||||
OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE,
|
||||
"Kerberos authentication mode. Valid values: SSPI, GSSAPI. If not specified, "
|
||||
"default is SSPI",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
#endif /* _WIN32 */
|
71
client/include/authentication_kerberos_clientopt-vars.h
Normal file
71
client/include/authentication_kerberos_clientopt-vars.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef AUTHETICATION_KERBEROS_CLIENTOPT_VARS_H
|
||||
#define AUTHETICATION_KERBEROS_CLIENTOPT_VARS_H
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "m_string.h"
|
||||
#include "mysql.h"
|
||||
#include "template_utils.h"
|
||||
#include "typelib.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
using std::snprintf;
|
||||
|
||||
const char *client_mode_names_lib[] = {"SSPI", "GSSAPI", NullS};
|
||||
|
||||
TYPELIB client_mode_typelib = {array_elements(client_mode_names_lib) - 1, "",
|
||||
client_mode_names_lib, nullptr};
|
||||
|
||||
static int opt_authentication_kerberos_client_mode = 0;
|
||||
|
||||
static int set_authentication_kerberos_client_mode(MYSQL *mysql, char *error,
|
||||
size_t error_size) {
|
||||
if (opt_authentication_kerberos_client_mode == 1) {
|
||||
struct st_mysql_client_plugin *kerberos_client_plugin =
|
||||
mysql_client_find_plugin(mysql, "authentication_kerberos_client",
|
||||
MYSQL_CLIENT_AUTHENTICATION_PLUGIN);
|
||||
if (!kerberos_client_plugin) {
|
||||
snprintf(error, error_size,
|
||||
"Failed to load plugin authentication_kerberos_client.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mysql_plugin_options(
|
||||
kerberos_client_plugin,
|
||||
"plugin_authentication_kerberos_client_mode",
|
||||
client_mode_names_lib[opt_authentication_kerberos_client_mode])) {
|
||||
snprintf(error, error_size,
|
||||
"Failed to set value '%s' for "
|
||||
"--plugin-authentication-kerberos-client-mode",
|
||||
client_mode_names_lib[opt_authentication_kerberos_client_mode]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif // !AUTHETICATION_KERBEROS_CLIENTOPT_VARS_H
|
32
client/include/authentication_webauthn_clientopt-case.h
Normal file
32
client/include/authentication_webauthn_clientopt-case.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* Copyright (c) 2023, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef AUTHENTICATION_WEBAUTHN_CLIENTOPT_CASE_H
|
||||
#define AUTHENTICATION_WEBAUTHN_CLIENTOPT_CASE_H
|
||||
|
||||
case OPT_AUTHENTICATION_WEBAUTHN_CLIENT_PRESERVE_PRIVACY:
|
||||
opt_authentication_webauthn_client_preserve_privacy =
|
||||
(argument != disabled_my_option);
|
||||
break;
|
||||
|
||||
#endif /* AUTHENTICATION_WEBAUTHN_CLIENTOPT_CASE_H */
|
44
client/include/authentication_webauthn_clientopt-longopts.h
Normal file
44
client/include/authentication_webauthn_clientopt-longopts.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* Copyright (c) 2023, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef AUTHENTICATION_WEBAUTHN_CLIENTOPT_LONGOPTS_H
|
||||
#define AUTHENTICATION_WEBAUTHN_CLIENTOPT_LONGOPTS_H
|
||||
|
||||
{"plugin_authentication_webauthn_client_preserve_privacy",
|
||||
OPT_AUTHENTICATION_WEBAUTHN_CLIENT_PRESERVE_PRIVACY,
|
||||
"Allows selection of discoverable credential to be used for signing "
|
||||
"challenge. "
|
||||
"default is false - implies challenge is signed by all credentials for "
|
||||
"given relying party.",
|
||||
&opt_authentication_webauthn_client_preserve_privacy,
|
||||
&opt_authentication_webauthn_client_preserve_privacy,
|
||||
nullptr,
|
||||
GET_BOOL,
|
||||
NO_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
#endif /* AUTHENTICATION_WEBAUTHN_CLIENTOPT_LONGOPTS_H */
|
57
client/include/authentication_webauthn_clientopt-vars.h
Normal file
57
client/include/authentication_webauthn_clientopt-vars.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* Copyright (c) 2023, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef AUTHENTICATION_WEBAUTH_CLIENTOPT_VARS_H
|
||||
#define AUTHENTICATION_WEBAUTH_CLIENTOPT_VARS_H
|
||||
|
||||
#include <cstdio>
|
||||
#include "mysql.h"
|
||||
|
||||
using std::snprintf;
|
||||
bool opt_authentication_webauthn_client_preserve_privacy = false;
|
||||
|
||||
static int set_authentication_webauthn_options(MYSQL *mysql, char *error,
|
||||
size_t error_size) {
|
||||
if (opt_authentication_webauthn_client_preserve_privacy) {
|
||||
struct st_mysql_client_plugin *webauthn_client_plugin =
|
||||
mysql_client_find_plugin(mysql, "authentication_webauthn_client",
|
||||
MYSQL_CLIENT_AUTHENTICATION_PLUGIN);
|
||||
if (!webauthn_client_plugin) {
|
||||
snprintf(error, error_size,
|
||||
"Failed to load authentication_webauthn_client.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mysql_plugin_options(
|
||||
webauthn_client_plugin,
|
||||
"authentication_webauthn_client_preserve_privacy",
|
||||
&opt_authentication_webauthn_client_preserve_privacy)) {
|
||||
snprintf(error, error_size,
|
||||
"Failed to set value 'TRUE' for "
|
||||
"--plugin-authentication-webauthn-client-preserve-privacy");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* AUTHENTICATION_WEBAUTH_CLIENTOPT_VARS_H */
|
55
client/include/caching_sha2_passwordopt-longopts.h
Normal file
55
client/include/caching_sha2_passwordopt-longopts.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/**
|
||||
@file include/caching_sha2_passwordopt-longopts.h
|
||||
*/
|
||||
|
||||
{"server-public-key-path",
|
||||
OPT_SERVER_PUBLIC_KEY,
|
||||
"File path to the server public RSA key in PEM format.",
|
||||
&opt_server_public_key,
|
||||
&opt_server_public_key,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"get-server-public-key",
|
||||
0,
|
||||
"Get server public key",
|
||||
&opt_get_server_public_key,
|
||||
&opt_get_server_public_key,
|
||||
nullptr,
|
||||
GET_BOOL,
|
||||
NO_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
46
client/include/caching_sha2_passwordopt-vars.h
Normal file
46
client/include/caching_sha2_passwordopt-vars.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/**
|
||||
@file include/caching_sha2_passwordopt-vars.h
|
||||
*/
|
||||
|
||||
#include "mysql.h"
|
||||
|
||||
static char *opt_server_public_key = nullptr;
|
||||
static bool opt_get_server_public_key = false;
|
||||
|
||||
static void set_server_public_key(MYSQL *mysql,
|
||||
const char *server_public_key = nullptr) {
|
||||
if (server_public_key && *server_public_key)
|
||||
mysql_options(mysql, MYSQL_SERVER_PUBLIC_KEY, server_public_key);
|
||||
else if (opt_server_public_key && *opt_server_public_key)
|
||||
mysql_options(mysql, MYSQL_SERVER_PUBLIC_KEY, opt_server_public_key);
|
||||
}
|
||||
|
||||
static void set_get_server_public_key_option(
|
||||
MYSQL *mysql, const bool *get_server_public_key = nullptr) {
|
||||
mysql_options(mysql, MYSQL_OPT_GET_SERVER_PUBLIC_KEY,
|
||||
get_server_public_key ? get_server_public_key
|
||||
: &opt_get_server_public_key);
|
||||
}
|
240
client/include/client_priv.h
Normal file
240
client/include/client_priv.h
Normal file
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
Copyright (c) 2001, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef CLIENT_PRIV_INCLUDED
|
||||
#define CLIENT_PRIV_INCLUDED
|
||||
|
||||
/* Common defines for all clients */
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
#include "errmsg.h"
|
||||
#include "my_getopt.h"
|
||||
#include "my_sys.h"
|
||||
|
||||
#ifndef WEXITSTATUS
|
||||
#ifdef _WIN32
|
||||
#define WEXITSTATUS(stat_val) (stat_val)
|
||||
#else
|
||||
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
enum options_client {
|
||||
OPT_CHARSETS_DIR = 256,
|
||||
OPT_DEFAULT_CHARSET,
|
||||
OPT_PAGER,
|
||||
OPT_TEE,
|
||||
OPT_LOW_PRIORITY,
|
||||
OPT_AUTO_REPAIR,
|
||||
OPT_COMPRESS,
|
||||
OPT_DROP,
|
||||
OPT_LOCKS,
|
||||
OPT_KEYWORDS,
|
||||
OPT_OPTIMIZE,
|
||||
OPT_FTB,
|
||||
OPT_LTB,
|
||||
OPT_ENC,
|
||||
OPT_O_ENC,
|
||||
OPT_ESC,
|
||||
OPT_TABLES,
|
||||
OPT_SOURCE_DATA,
|
||||
OPT_AUTOCOMMIT,
|
||||
OPT_AUTO_REHASH,
|
||||
OPT_LINE_NUMBERS,
|
||||
OPT_COLUMN_NAMES,
|
||||
OPT_CONNECT_TIMEOUT,
|
||||
OPT_MAX_ALLOWED_PACKET,
|
||||
OPT_NET_BUFFER_LENGTH,
|
||||
OPT_SELECT_LIMIT,
|
||||
OPT_MAX_JOIN_SIZE,
|
||||
OPT_SSL_SSL,
|
||||
OPT_SSL_KEY,
|
||||
OPT_SSL_CERT,
|
||||
OPT_SSL_CA,
|
||||
OPT_SSL_CAPATH,
|
||||
OPT_SSL_CIPHER,
|
||||
OPT_SHUTDOWN_TIMEOUT,
|
||||
OPT_LOCAL_INFILE,
|
||||
OPT_DELETE_SOURCE_LOGS,
|
||||
OPT_COMPACT,
|
||||
OPT_PROMPT,
|
||||
OPT_IGN_LINES,
|
||||
OPT_TRANSACTION,
|
||||
OPT_MYSQL_PROTOCOL,
|
||||
OPT_SHARED_MEMORY_BASE_NAME,
|
||||
OPT_FRM,
|
||||
OPT_SKIP_OPTIMIZATION,
|
||||
OPT_COMPATIBLE,
|
||||
OPT_RECONNECT,
|
||||
OPT_DELIMITER,
|
||||
OPT_OPEN_FILES_LIMIT,
|
||||
OPT_SET_CHARSET,
|
||||
OPT_SET_GTID_PURGED,
|
||||
OPT_STOP_POSITION,
|
||||
OPT_START_DATETIME,
|
||||
OPT_STOP_DATETIME,
|
||||
OPT_SIGINT_IGNORE,
|
||||
OPT_HEXBLOB,
|
||||
OPT_ORDER_BY_PRIMARY,
|
||||
OPT_COUNT,
|
||||
OPT_TRIGGERS,
|
||||
OPT_MYSQL_ONLY_PRINT,
|
||||
OPT_MYSQL_LOCK_DIRECTORY,
|
||||
OPT_USE_THREADS,
|
||||
OPT_IMPORT_USE_THREADS,
|
||||
OPT_MYSQL_NUMBER_OF_QUERY,
|
||||
OPT_IGNORE_TABLE,
|
||||
OPT_INSERT_IGNORE,
|
||||
OPT_SHOW_WARNINGS,
|
||||
OPT_DROP_DATABASE,
|
||||
OPT_TZ_UTC,
|
||||
OPT_CREATE_SLAP_SCHEMA,
|
||||
OPT_MYSQLDUMP_REPLICA_APPLY,
|
||||
OPT_MYSQLDUMP_REPLICA_DATA,
|
||||
OPT_MYSQLDUMP_INCLUDE_SOURCE_HOST_PORT,
|
||||
OPT_MYSQLDUMP_IGNORE_ERROR,
|
||||
OPT_SLAP_CSV,
|
||||
OPT_SLAP_CREATE_STRING,
|
||||
OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE,
|
||||
OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
|
||||
OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
|
||||
OPT_SLAP_AUTO_GENERATE_GUID_PRIMARY,
|
||||
OPT_SLAP_AUTO_GENERATE_EXECUTE_QUERIES,
|
||||
OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES,
|
||||
OPT_SLAP_AUTO_GENERATE_UNIQUE_WRITE_NUM,
|
||||
OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
|
||||
OPT_SLAP_PRE_QUERY,
|
||||
OPT_SLAP_POST_QUERY,
|
||||
OPT_SLAP_PRE_SYSTEM,
|
||||
OPT_SLAP_POST_SYSTEM,
|
||||
OPT_SLAP_COMMIT,
|
||||
OPT_SLAP_DETACH,
|
||||
OPT_SLAP_NO_DROP,
|
||||
OPT_MYSQL_REPLACE_INTO,
|
||||
OPT_BASE64_OUTPUT_MODE,
|
||||
OPT_SERVER_ID,
|
||||
OPT_FIX_TABLE_NAMES,
|
||||
OPT_FIX_DB_NAMES,
|
||||
OPT_SSL_VERIFY_SERVER_CERT,
|
||||
OPT_AUTO_VERTICAL_OUTPUT,
|
||||
OPT_DEBUG_INFO,
|
||||
OPT_DEBUG_CHECK,
|
||||
OPT_COLUMN_TYPES,
|
||||
OPT_ERROR_LOG_FILE,
|
||||
OPT_WRITE_BINLOG,
|
||||
OPT_DUMP_DATE,
|
||||
OPT_INIT_COMMAND,
|
||||
OPT_PLUGIN_DIR,
|
||||
OPT_DEFAULT_AUTH,
|
||||
OPT_DEFAULT_PLUGIN,
|
||||
OPT_RAW_OUTPUT,
|
||||
OPT_WAIT_SERVER_ID,
|
||||
OPT_STOP_NEVER,
|
||||
OPT_BINLOG_ROWS_EVENT_MAX_SIZE,
|
||||
OPT_HISTIGNORE,
|
||||
OPT_BINARY_MODE,
|
||||
OPT_SSL_CRL,
|
||||
OPT_SSL_CRLPATH,
|
||||
OPT_MYSQLBINLOG_SKIP_GTIDS,
|
||||
OPT_MYSQLBINLOG_INCLUDE_GTIDS,
|
||||
OPT_MYSQLBINLOG_EXCLUDE_GTIDS,
|
||||
OPT_REMOTE_PROTO,
|
||||
OPT_CONFIG_ALL,
|
||||
OPT_REWRITE_DB,
|
||||
OPT_SERVER_PUBLIC_KEY,
|
||||
OPT_ENABLE_CLEARTEXT_PLUGIN,
|
||||
OPT_CONNECTION_SERVER_ID,
|
||||
OPT_TLS_VERSION,
|
||||
OPT_SSL_MODE,
|
||||
OPT_PRINT_TABLE_METADATA,
|
||||
OPT_SSL_FIPS_MODE,
|
||||
OPT_TLS_CIPHERSUITES,
|
||||
OPT_MYSQL_BINARY_AS_HEX,
|
||||
OPT_LOAD_DATA_LOCAL_DIR,
|
||||
OPT_READ_FROM_REMOTE_MASTER_DEPRECATED,
|
||||
OPT_MASTER_DATA_DEPRECATED,
|
||||
OPT_MYSQLDUMP_SLAVE_APPLY_DEPRECATED,
|
||||
OPT_DELETE_MASTER_LOGS_DEPRECATED,
|
||||
OPT_MYSQLDUMP_SLAVE_DATA_DEPRECATED,
|
||||
OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT_DEPRECATED,
|
||||
OPT_SSL_SESSION_DATA,
|
||||
OPT_SSL_SESSION_DATA_CONTINUE_ON_FAILED_REUSE,
|
||||
OPT_LONG_QUERY_TIME,
|
||||
OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE,
|
||||
OPT_TLS_SNI_SERVERNAME,
|
||||
OPT_INIT_COMMAND_ADD,
|
||||
OPT_OUTPUT_AS_VERSION,
|
||||
OPT_AUTHENTICATION_WEBAUTHN_CLIENT_PRESERVE_PRIVACY,
|
||||
/* Add new option above this */
|
||||
OPT_MAX_CLIENT_OPTION
|
||||
};
|
||||
|
||||
/**
|
||||
First mysql version supporting the information schema.
|
||||
*/
|
||||
#define FIRST_INFORMATION_SCHEMA_VERSION 50003
|
||||
|
||||
/**
|
||||
Name of the information schema database.
|
||||
*/
|
||||
#define INFORMATION_SCHEMA_DB_NAME "information_schema"
|
||||
|
||||
/**
|
||||
First mysql version supporting the performance schema.
|
||||
*/
|
||||
#define FIRST_PERFORMANCE_SCHEMA_VERSION 50503
|
||||
|
||||
/**
|
||||
Name of the performance schema database.
|
||||
*/
|
||||
#define PERFORMANCE_SCHEMA_DB_NAME "performance_schema"
|
||||
|
||||
/**
|
||||
First mysql version supporting the sys schema.
|
||||
*/
|
||||
#define FIRST_SYS_SCHEMA_VERSION 50707
|
||||
|
||||
/**
|
||||
Name of the sys schema database.
|
||||
*/
|
||||
#define SYS_SCHEMA_DB_NAME "sys"
|
||||
|
||||
/**
|
||||
Client deprecation warnings
|
||||
*/
|
||||
#define CLIENT_WARN_DEPRECATED_NO_REPLACEMENT_MSG(opt) \
|
||||
opt " is deprecated and will be removed in a future version\n"
|
||||
|
||||
#define CLIENT_WARN_DEPRECATED_MSG(opt, new_opt) \
|
||||
opt " is deprecated and will be removed in a future version. " \
|
||||
"Use " new_opt " instead.\n"
|
||||
|
||||
#define CLIENT_WARN_DEPRECATED_NO_REPLACEMENT(opt) \
|
||||
fprintf(stderr, "WARNING: " CLIENT_WARN_DEPRECATED_NO_REPLACEMENT_MSG(opt))
|
||||
|
||||
#define CLIENT_WARN_DEPRECATED(opt, new_opt) \
|
||||
fprintf(stderr, "WARNING: " CLIENT_WARN_DEPRECATED_MSG(opt, new_opt))
|
||||
#endif
|
93
client/include/multi_factor_passwordopt-longopts.h
Normal file
93
client/include/multi_factor_passwordopt-longopts.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
/* Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/**
|
||||
@file include/multi_factor_passwordopt-longopts.h
|
||||
|
||||
This file contains password options to be specified as part of command-line
|
||||
options for first,second,third authentication plugin factors for a given user.
|
||||
*/
|
||||
|
||||
/* preserve existing option for backward compatibility */
|
||||
{"password",
|
||||
'p',
|
||||
"Password to use when connecting to server. If password is not given it's "
|
||||
"asked from the tty.",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
GET_PASSWORD,
|
||||
OPT_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
/*
|
||||
--password1, --password2 --password3 are new options to handle password for
|
||||
first, second and third factor authentication plugin defined for a given
|
||||
user account
|
||||
*/
|
||||
{"password1",
|
||||
MYSQL_OPT_USER_PASSWORD,
|
||||
"Password for first factor authentication plugin.",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
GET_PASSWORD,
|
||||
OPT_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"password2",
|
||||
MYSQL_OPT_USER_PASSWORD,
|
||||
"Password for second factor authentication plugin.",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
GET_PASSWORD,
|
||||
OPT_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"password3",
|
||||
MYSQL_OPT_USER_PASSWORD,
|
||||
"Password for third factor authentication plugin.",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
GET_PASSWORD,
|
||||
OPT_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
48
client/include/multi_factor_passwordopt-vars.h
Normal file
48
client/include/multi_factor_passwordopt-vars.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef MULTI_FACTOR_PASSWORDOPT_VARS_H
|
||||
#define MULTI_FACTOR_PASSWORDOPT_VARS_H
|
||||
|
||||
#include "mysql.h"
|
||||
|
||||
extern char *opt_password[MAX_AUTH_FACTORS];
|
||||
extern bool tty_password[MAX_AUTH_FACTORS];
|
||||
|
||||
/** parse passwords for --password or --password<N> option where N = 1,2,3 */
|
||||
void parse_command_line_password_option(const struct my_option *opt,
|
||||
char *argument);
|
||||
/** Set password in mysql->options */
|
||||
void set_password_options(MYSQL *mysql);
|
||||
/** Release memory for opt_password */
|
||||
void free_passwords();
|
||||
|
||||
#define PARSE_COMMAND_LINE_PASSWORD_OPTION \
|
||||
case 'p': \
|
||||
parse_command_line_password_option(opt, argument); \
|
||||
break; \
|
||||
case MYSQL_OPT_USER_PASSWORD: \
|
||||
parse_command_line_password_option(opt, argument); \
|
||||
break;
|
||||
|
||||
#endif // MULTI_FACTOR_PASSWORDOPT_VARS_H
|
49
client/include/sslopt-case.h
Normal file
49
client/include/sslopt-case.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifdef MYSQL_SERVER
|
||||
#error This header is supposed to be used only in the client
|
||||
#endif
|
||||
|
||||
case OPT_SSL_MODE:
|
||||
opt_ssl_mode = find_type_or_exit(argument, &ssl_mode_typelib, opt->name);
|
||||
ssl_mode_set_explicitly = true;
|
||||
break;
|
||||
case OPT_SSL_FIPS_MODE:
|
||||
opt_ssl_fips_mode =
|
||||
find_type_or_exit(argument, &ssl_fips_mode_typelib, opt->name) - 1;
|
||||
break;
|
||||
case OPT_SSL_CA:
|
||||
case OPT_SSL_CAPATH:
|
||||
/* Don't change ssl-mode if set explicitly. */
|
||||
if (!ssl_mode_set_explicitly) opt_ssl_mode = SSL_MODE_VERIFY_CA;
|
||||
break;
|
||||
case OPT_SSL_KEY:
|
||||
case OPT_SSL_CERT:
|
||||
case OPT_SSL_CIPHER:
|
||||
case OPT_SSL_CRL:
|
||||
case OPT_SSL_CRLPATH:
|
||||
case OPT_TLS_VERSION:
|
||||
case OPT_SSL_SESSION_DATA:
|
||||
case OPT_TLS_SNI_SERVERNAME:
|
||||
break;
|
230
client/include/sslopt-longopts.h
Normal file
230
client/include/sslopt-longopts.h
Normal file
|
@ -0,0 +1,230 @@
|
|||
/* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/**
|
||||
@file include/sslopt-longopts.h
|
||||
*/
|
||||
|
||||
{"ssl-mode",
|
||||
OPT_SSL_MODE,
|
||||
"SSL connection mode.",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"ssl-ca",
|
||||
OPT_SSL_CA,
|
||||
"CA file in PEM format.",
|
||||
&opt_ssl_ca,
|
||||
&opt_ssl_ca,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"ssl-capath",
|
||||
OPT_SSL_CAPATH,
|
||||
"CA directory.",
|
||||
&opt_ssl_capath,
|
||||
&opt_ssl_capath,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"ssl-cert",
|
||||
OPT_SSL_CERT,
|
||||
"X509 cert in PEM format.",
|
||||
&opt_ssl_cert,
|
||||
&opt_ssl_cert,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"ssl-cipher",
|
||||
OPT_SSL_CIPHER,
|
||||
"SSL cipher to use.",
|
||||
&opt_ssl_cipher,
|
||||
&opt_ssl_cipher,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"ssl-key",
|
||||
OPT_SSL_KEY,
|
||||
"X509 key in PEM format.",
|
||||
&opt_ssl_key,
|
||||
&opt_ssl_key,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"ssl-crl",
|
||||
OPT_SSL_CRL,
|
||||
"Certificate revocation list.",
|
||||
&opt_ssl_crl,
|
||||
&opt_ssl_crl,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"ssl-crlpath",
|
||||
OPT_SSL_CRLPATH,
|
||||
"Certificate revocation list path.",
|
||||
&opt_ssl_crlpath,
|
||||
&opt_ssl_crlpath,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"tls-version",
|
||||
OPT_TLS_VERSION,
|
||||
"TLS version to use, "
|
||||
#ifdef HAVE_TLSv13
|
||||
"permitted values are: TLSv1.2, TLSv1.3",
|
||||
#else
|
||||
"permitted values are: TLSv1.2",
|
||||
#endif
|
||||
&opt_tls_version,
|
||||
&opt_tls_version,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"ssl-fips-mode",
|
||||
OPT_SSL_FIPS_MODE,
|
||||
"SSL FIPS mode (applies only for OpenSSL); "
|
||||
"permitted values are: OFF, ON, STRICT",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"tls-ciphersuites",
|
||||
OPT_TLS_CIPHERSUITES,
|
||||
"TLS v1.3 cipher to use.",
|
||||
&opt_tls_ciphersuites,
|
||||
&opt_tls_ciphersuites,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"ssl-session-data",
|
||||
OPT_SSL_SESSION_DATA,
|
||||
"Session data file to use to enable ssl session reuse",
|
||||
&opt_ssl_session_data,
|
||||
&opt_ssl_session_data,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"ssl-session-data-continue-on-failed-reuse",
|
||||
OPT_SSL_SESSION_DATA_CONTINUE_ON_FAILED_REUSE,
|
||||
"If set to ON, this option will allow connection to succeed even if "
|
||||
"session data cannot be reused.",
|
||||
&opt_ssl_session_data_continue_on_failed_reuse,
|
||||
&opt_ssl_session_data_continue_on_failed_reuse,
|
||||
nullptr,
|
||||
GET_BOOL,
|
||||
OPT_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
||||
{"tls-sni-servername",
|
||||
OPT_TLS_SNI_SERVERNAME,
|
||||
"The SNI server name to pass to server",
|
||||
&opt_tls_sni_servername,
|
||||
&opt_tls_sni_servername,
|
||||
nullptr,
|
||||
GET_STR,
|
||||
REQUIRED_ARG,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr},
|
162
client/include/sslopt-vars.h
Normal file
162
client/include/sslopt-vars.h
Normal file
|
@ -0,0 +1,162 @@
|
|||
/* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef SSLOPT_VARS_INCLUDED
|
||||
#define SSLOPT_VARS_INCLUDED
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <functional>
|
||||
|
||||
#ifdef MYSQL_SERVER
|
||||
#error This header is supposed to be used only in the client
|
||||
#endif
|
||||
|
||||
#include "my_inttypes.h"
|
||||
#include "my_macros.h"
|
||||
#include "mysql.h"
|
||||
#include "nulls.h"
|
||||
#include "template_utils.h"
|
||||
#include "typelib.h"
|
||||
|
||||
const char *ssl_mode_names_lib[] = {"DISABLED", "PREFERRED", "REQUIRED",
|
||||
"VERIFY_CA", "VERIFY_IDENTITY", NullS};
|
||||
TYPELIB ssl_mode_typelib = {array_elements(ssl_mode_names_lib) - 1, "",
|
||||
ssl_mode_names_lib, nullptr};
|
||||
|
||||
const char *ssl_fips_mode_names_lib[] = {"OFF", "ON", "STRICT", NullS};
|
||||
TYPELIB ssl_fips_mode_typelib = {array_elements(ssl_fips_mode_names_lib) - 1,
|
||||
"", ssl_fips_mode_names_lib, nullptr};
|
||||
|
||||
static uint opt_ssl_mode = SSL_MODE_PREFERRED;
|
||||
static char *opt_ssl_ca = nullptr;
|
||||
static char *opt_ssl_capath = nullptr;
|
||||
static char *opt_ssl_cert = nullptr;
|
||||
static char *opt_ssl_cipher = nullptr;
|
||||
static char *opt_tls_ciphersuites = nullptr;
|
||||
static char *opt_ssl_key = nullptr;
|
||||
static char *opt_ssl_crl = nullptr;
|
||||
static char *opt_ssl_crlpath = nullptr;
|
||||
static char *opt_tls_version = nullptr;
|
||||
static ulong opt_ssl_fips_mode = SSL_FIPS_MODE_OFF;
|
||||
static bool ssl_mode_set_explicitly = false;
|
||||
static char *opt_ssl_session_data = nullptr;
|
||||
static bool opt_ssl_session_data_continue_on_failed_reuse = false;
|
||||
static char *opt_tls_sni_servername = nullptr;
|
||||
|
||||
static inline int set_client_ssl_options(MYSQL *mysql) {
|
||||
/*
|
||||
Print a warning if explicitly defined combination of --ssl-mode other than
|
||||
VERIFY_CA or VERIFY_IDENTITY with explicit --ssl-ca or --ssl-capath values.
|
||||
*/
|
||||
if (ssl_mode_set_explicitly && opt_ssl_mode < SSL_MODE_VERIFY_CA &&
|
||||
(opt_ssl_ca || opt_ssl_capath)) {
|
||||
fprintf(stderr,
|
||||
"WARNING: no verification of server certificate will be done. "
|
||||
"Use --ssl-mode=VERIFY_CA or VERIFY_IDENTITY.\n");
|
||||
}
|
||||
|
||||
/* Set SSL parameters: key, cert, ca, capath, cipher, clr, clrpath. */
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_KEY, opt_ssl_key);
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_CERT, opt_ssl_cert);
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_CIPHER, opt_ssl_cipher);
|
||||
if (opt_ssl_mode >= SSL_MODE_VERIFY_CA) {
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_CA, opt_ssl_ca);
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_CAPATH, opt_ssl_capath);
|
||||
} else {
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_CA, nullptr);
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_CAPATH, nullptr);
|
||||
}
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
|
||||
mysql_options(mysql, MYSQL_OPT_TLS_VERSION, opt_tls_version);
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_MODE, &opt_ssl_mode);
|
||||
if (opt_ssl_fips_mode > 0) {
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_FIPS_MODE, &opt_ssl_fips_mode);
|
||||
if (mysql_errno(mysql) == CR_SSL_FIPS_MODE_ERR) return 1;
|
||||
}
|
||||
mysql_options(mysql, MYSQL_OPT_TLS_CIPHERSUITES, opt_tls_ciphersuites);
|
||||
mysql_options(mysql, MYSQL_OPT_TLS_SNI_SERVERNAME, opt_tls_sni_servername);
|
||||
if (opt_ssl_session_data) {
|
||||
FILE *fi = fopen(opt_ssl_session_data, "rb");
|
||||
char buff[4096], *bufptr = &buff[0];
|
||||
size_t read = 0;
|
||||
|
||||
if (!fi) {
|
||||
fprintf(stderr, "Error: Can't open the ssl session data file.\n");
|
||||
return 1;
|
||||
}
|
||||
long file_length = sizeof(buff) - 1;
|
||||
if (0 == fseek(fi, 0, SEEK_END)) {
|
||||
file_length = ftell(fi);
|
||||
if (file_length > 0)
|
||||
file_length = std::min(file_length, 65536L);
|
||||
else
|
||||
file_length = sizeof(buff) - 1;
|
||||
fseek(fi, 0, SEEK_SET);
|
||||
}
|
||||
if (file_length > (long)(sizeof(buff) - 1)) {
|
||||
bufptr = (char *)malloc(file_length + 1);
|
||||
if (bufptr)
|
||||
bufptr[file_length] = 0;
|
||||
else {
|
||||
bufptr = &buff[0];
|
||||
file_length = sizeof(buff) - 1;
|
||||
}
|
||||
}
|
||||
read = fread(bufptr, 1, file_length, fi);
|
||||
if (!read) {
|
||||
fprintf(stderr, "Error: Can't read the ssl session data file.\n");
|
||||
fclose(fi);
|
||||
if (bufptr != &buff[0]) free(bufptr);
|
||||
return 1;
|
||||
}
|
||||
assert(read <= (size_t)file_length);
|
||||
bufptr[read] = 0;
|
||||
fclose(fi);
|
||||
|
||||
int ret = 0;
|
||||
if (read) ret = mysql_options(mysql, MYSQL_OPT_SSL_SESSION_DATA, buff);
|
||||
if (bufptr != &buff[0]) free(bufptr);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static bool ssl_client_check_post_connect_ssl_setup(
|
||||
MYSQL *mysql, std::function<void(const char *)> report_error) {
|
||||
if (opt_ssl_session_data && !opt_ssl_session_data_continue_on_failed_reuse &&
|
||||
!mysql_get_ssl_session_reused(mysql)) {
|
||||
report_error(
|
||||
"--ssl-session-data specified but the session was not reused.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define SSL_SET_OPTIONS(mysql) set_client_ssl_options(mysql)
|
||||
|
||||
const char *SSL_SET_OPTIONS_ERROR = "Failed to set ssl related options.\n";
|
||||
|
||||
#endif /* SSLOPT_VARS_INCLUDED */
|
34
client/include/user_registration.h
Normal file
34
client/include/user_registration.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef USER_REGISTRATION_H_
|
||||
#define USER_REGISTRATION_H_
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
bool user_device_registration(MYSQL *mysql_handle, char *register_option,
|
||||
char *errmsg);
|
||||
|
||||
#endif // USER_REGISTRATION_H_
|
58
client/infix_ostream_it.h
Normal file
58
client/infix_ostream_it.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Copyright (c) 2012, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef INFIX_OSTREAM_IT_INCLUDED
|
||||
#define INFIX_OSTREAM_IT_INCLUDED
|
||||
#include <iterator>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
template <class T>
|
||||
class infix_ostream_iterator
|
||||
: public std::iterator<std::output_iterator_tag, T> {
|
||||
public:
|
||||
explicit infix_ostream_iterator(std::ostream &s) : m_os(&s) {}
|
||||
|
||||
infix_ostream_iterator(std::ostream &s, const char *d)
|
||||
: m_os(&s), m_delimiter(d) {}
|
||||
|
||||
infix_ostream_iterator<T> &operator=(T const &item) {
|
||||
*m_os << m_curr_delimiter << item;
|
||||
m_curr_delimiter = m_delimiter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
infix_ostream_iterator<T> &operator*() { return *this; }
|
||||
|
||||
infix_ostream_iterator<T> &operator++() { return *this; }
|
||||
|
||||
infix_ostream_iterator<T> &operator++(int) { return *this; }
|
||||
|
||||
private:
|
||||
std::ostream *m_os;
|
||||
std::string m_curr_delimiter;
|
||||
std::string m_delimiter;
|
||||
};
|
||||
|
||||
#endif
|
42
client/json_binlog.ver
Normal file
42
client/json_binlog.ver
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* Copyright (c) 2020, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/*
|
||||
These are the functions used by mysqlbinlog:
|
||||
Json_wrapper::to_string(String*, bool, char const*) const
|
||||
Json_wrapper::type() const
|
||||
Json_wrapper::Json_wrapper(json_binary::Value const&)
|
||||
Json_wrapper::~Json_wrapper()
|
||||
json_binary::parse_binary(char const*, unsigned long)
|
||||
*/
|
||||
|
||||
{
|
||||
global:
|
||||
extern "C++" {
|
||||
*Json_wrapper*;
|
||||
json_binary::*;
|
||||
};
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
65
client/json_binlog_main.cc
Normal file
65
client/json_binlog_main.cc
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* Copyright (c) 2020, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/*
|
||||
This is a test executable which does nothing, except verify that symbols are
|
||||
visible. See the accompanying cmake rules.
|
||||
Instantiated Value objects are bad, running this executable will fail.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "sql-common/json_binary.h"
|
||||
|
||||
int main() {
|
||||
json_binary::Value value = json_binary::parse_binary(nullptr, 0);
|
||||
|
||||
const bool is_valid = value.is_valid();
|
||||
const json_binary::Value::enum_type enum_type = value.type();
|
||||
|
||||
value = json_binary::Value(json_binary::Value::OBJECT, nullptr, 0, 1, false);
|
||||
|
||||
const json_binary::Value elt1 = value.element(1);
|
||||
const json_binary::Value key1 = value.key(1);
|
||||
|
||||
const size_t sz1 = value.lookup_index("foo", 3);
|
||||
const size_t sz2 = value.lookup_index(std::string("foo"));
|
||||
|
||||
const bool has_space = value.has_space(0, 0, nullptr);
|
||||
|
||||
const json_binary::Value null_value =
|
||||
json_binary::Value(json_binary::Value::LITERAL_NULL);
|
||||
|
||||
const json_binary::Value int_value =
|
||||
json_binary::Value(json_binary::Value::INT, 42);
|
||||
|
||||
const json_binary::Value double_value = json_binary::Value(0.0);
|
||||
|
||||
const json_binary::Value string_value = json_binary::Value("foo", 3);
|
||||
|
||||
std::string string_buf;
|
||||
string_value.to_std_string(&string_buf, [] { assert(false); });
|
||||
string_value.to_pretty_std_string(&string_buf, [] { assert(false); });
|
||||
return 0;
|
||||
}
|
322
client/json_client_library_main.cc
Normal file
322
client/json_client_library_main.cc
Normal file
|
@ -0,0 +1,322 @@
|
|||
/* Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/*
|
||||
This is a test executable which verifies that Json_wrapper::seek,
|
||||
Json_dom::seek, Json_dom::parse, json_binary::parse_binary,
|
||||
json_binary::serialize functions are visible and can be called.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "field_types.h"
|
||||
#include "mysql/components/services/bits/psi_bits.h"
|
||||
#include "mysql_time.h"
|
||||
#include "sql-common/json_binary.h"
|
||||
#include "sql-common/json_dom.h"
|
||||
#include "sql-common/json_error_handler.h"
|
||||
#include "sql-common/json_path.h"
|
||||
#include "sql-common/my_decimal.h"
|
||||
#include "sql_string.h"
|
||||
#include "template_utils.h"
|
||||
|
||||
namespace {
|
||||
void CoutDefaultDepthHandler() { std::cout << "Doc too deep"; }
|
||||
|
||||
class CoutSerializationErrorHandler : public JsonSerializationErrorHandler {
|
||||
public:
|
||||
void KeyTooBig() const override { std::cout << "Key too big"; }
|
||||
void ValueTooBig() const override { std::cout << "Value too big"; }
|
||||
void TooDeep() const override { CoutDefaultDepthHandler(); }
|
||||
void InvalidJson() const override { std::cout << "Invalid JSON"; }
|
||||
void InternalError(const char *message) const override {
|
||||
std::cout << "Internal error: " << message;
|
||||
}
|
||||
bool CheckStack() const override {
|
||||
std::cout << "Checking stack\n";
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
Json_object o;
|
||||
for (size_t i = 0; i < 1000; ++i) {
|
||||
o.add_alias(std::to_string(i),
|
||||
new (std::nothrow)
|
||||
Json_string(std::string("key_") + std::to_string(i)));
|
||||
}
|
||||
|
||||
// Make sure Json_wrapper::seek is visible
|
||||
Json_wrapper_vector hits(PSI_NOT_INSTRUMENTED);
|
||||
const bool need_only_one{false};
|
||||
const char *json_path = R"($**."512")";
|
||||
Json_path path(PSI_NOT_INSTRUMENTED);
|
||||
size_t bad_index;
|
||||
parse_path(std::strlen(json_path), json_path, &path, &bad_index);
|
||||
|
||||
Json_wrapper wr(&o);
|
||||
wr.set_alias();
|
||||
|
||||
StringBuffer<20000> buf;
|
||||
if (wr.to_binary(CoutSerializationErrorHandler(), &buf)) {
|
||||
std::cout << "error";
|
||||
} else {
|
||||
const json_binary::Value v(
|
||||
json_binary::parse_binary(buf.ptr(), buf.length()));
|
||||
std::string std_string;
|
||||
v.to_pretty_std_string(&std_string, CoutDefaultDepthHandler);
|
||||
std::cout << "1. Binary_val[" << std_string << "]" << std::endl;
|
||||
}
|
||||
|
||||
wr.seek(path, path.leg_count(), &hits, true, need_only_one);
|
||||
|
||||
for (auto &hit : hits) {
|
||||
String buffer;
|
||||
hit.to_string(&buffer, false, nullptr, [] { assert(false); });
|
||||
std::cout << std::string_view{buffer.ptr(), buffer.length()} << std::endl;
|
||||
}
|
||||
|
||||
// Make sure Json_dom::parse is visible and error handling works
|
||||
{
|
||||
const std::string json{"[{\"key\":123},146]"};
|
||||
Json_dom_ptr dom(Json_dom::parse(
|
||||
json.c_str(), json.length(),
|
||||
[](const char *, size_t) { assert(false); }, [] { assert(false); }));
|
||||
if (dom != nullptr) std::cout << "1. success" << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
const std::string json{
|
||||
"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
|
||||
R"([[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{"key":123}]]]]]]]]]]]]]]]]]]]]]]]]]])"
|
||||
"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
|
||||
"]]]]"};
|
||||
Json_dom_ptr dom(Json_dom::parse(
|
||||
json.c_str(), json.length(),
|
||||
[](const char *err_mesg, size_t err_code) {
|
||||
std::cout << "2. parse_error [" << err_code << "]: " << err_mesg
|
||||
<< std::endl;
|
||||
},
|
||||
[] { std::cout << "2. depth_error" << std::endl; }));
|
||||
if (dom != nullptr) assert(false);
|
||||
}
|
||||
|
||||
{
|
||||
const std::string json{"[&&"};
|
||||
Json_dom_ptr dom(Json_dom::parse(
|
||||
json.c_str(), json.length(),
|
||||
[](const char *err_mesg, size_t err_code) {
|
||||
std::cout << "3. parse_error [" << err_code << "]: " << err_mesg
|
||||
<< std::endl;
|
||||
},
|
||||
[] { assert(false); }));
|
||||
if (dom != nullptr) assert(false);
|
||||
}
|
||||
|
||||
{
|
||||
my_decimal m;
|
||||
double2my_decimal(0, 3.14000000001, &m);
|
||||
const Json_decimal jd(m);
|
||||
if (json_binary::serialize(&jd, CoutSerializationErrorHandler(), &buf))
|
||||
std::cout << "ERRROR!!" << std::endl;
|
||||
|
||||
json_binary::Value v = json_binary::parse_binary(buf.ptr(), buf.length());
|
||||
std::string std_string;
|
||||
if (v.to_std_string(&std_string, CoutDefaultDepthHandler))
|
||||
std::cout << "ERRROR!!" << std::endl;
|
||||
std::cout << "4. val[" << std_string << "]" << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
/* DATETIME scalar */
|
||||
MYSQL_TIME dt;
|
||||
std::memset(&dt, 0, sizeof dt);
|
||||
dt.year = 1988;
|
||||
dt.month = 12;
|
||||
dt.day = 15;
|
||||
dt.time_type = MYSQL_TIMESTAMP_DATE;
|
||||
const Json_datetime jd(dt, MYSQL_TYPE_DATETIME);
|
||||
|
||||
if (json_binary::serialize(&jd, CoutSerializationErrorHandler(), &buf))
|
||||
std::cout << "ERRROR!!" << std::endl;
|
||||
|
||||
json_binary::Value v = json_binary::parse_binary(buf.ptr(), buf.length());
|
||||
|
||||
// Test call to get_free_space.
|
||||
size_t free_space;
|
||||
v.get_free_space(CoutSerializationErrorHandler(), &free_space);
|
||||
std::cout << "5.1. free space: " << free_space << std::endl;
|
||||
|
||||
std::string std_string;
|
||||
if (v.to_pretty_std_string(&std_string, CoutDefaultDepthHandler))
|
||||
std::cout << "ERRROR!!" << std::endl;
|
||||
std::cout << "5.2. val[" << std_string << "]" << std::endl;
|
||||
}
|
||||
|
||||
// Test if contains_wr is exposed
|
||||
{
|
||||
const std::string json_1{"[{\"key\":123},146]"};
|
||||
Json_dom_ptr dom1(Json_dom::parse(
|
||||
json_1.c_str(), json_1.length(),
|
||||
[](const char *, size_t) { assert(false); }, [] { assert(false); }));
|
||||
Json_wrapper json_wrapper = Json_wrapper(std::move(dom1));
|
||||
|
||||
const std::string json_2{"{\"key\":123}"};
|
||||
Json_dom_ptr dom2(Json_dom::parse(
|
||||
json_2.c_str(), json_2.length(),
|
||||
[](const char *, size_t) { assert(false); }, [] { assert(false); }));
|
||||
Json_wrapper json_containee = Json_wrapper(std::move(dom2));
|
||||
|
||||
bool result;
|
||||
if (json_wrapper_contains(json_wrapper, json_containee, &result)) {
|
||||
assert(false);
|
||||
} else {
|
||||
std::cout << "6.1. it is: " << std::boolalpha << result
|
||||
<< " that json_1 contains json_2\n";
|
||||
}
|
||||
if (json_wrapper_contains(json_containee, json_wrapper, &result)) {
|
||||
assert(false);
|
||||
} else {
|
||||
std::cout << "6.2. it is: " << std::boolalpha << result
|
||||
<< " that json_2 contains json_1\n";
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const std::string json{"[\"Alice2\", 225, 165.5, 155.2, \"female\"]"};
|
||||
Json_dom_ptr dom(Json_dom::parse(
|
||||
json.c_str(), json.length(),
|
||||
[](const char *, size_t) { assert(false); }, [] { assert(false); }));
|
||||
Json_array *arr = down_cast<Json_array *>(dom.get());
|
||||
|
||||
Json_dom_ptr dom1(Json_dom::parse(
|
||||
"1", 1, [](const char *, size_t) { assert(false); },
|
||||
[] { assert(false); }));
|
||||
Json_dom_ptr dom2(Json_dom::parse(
|
||||
"155.2", 5, [](const char *, size_t) { assert(false); },
|
||||
[] { assert(false); }));
|
||||
|
||||
// Sort array and use binary search to lookup values
|
||||
arr->sort();
|
||||
bool result = arr->binary_search(dom1.get());
|
||||
std::cout << "7.1. it is: " << std::boolalpha << result
|
||||
<< " that array contains 1\n";
|
||||
|
||||
result = arr->binary_search(dom2.get());
|
||||
std::cout << "7.2. it is: " << std::boolalpha << result
|
||||
<< " that array contains 155.2\n";
|
||||
}
|
||||
|
||||
// Make sure json_type_name() is visible.
|
||||
{
|
||||
std::cout << "8.1. Type of empty wrapper is "
|
||||
<< json_type_name(Json_wrapper{}) << ".\n";
|
||||
{
|
||||
Json_array array;
|
||||
std::cout << "8.2. Type of array is "
|
||||
<< json_type_name(Json_wrapper{&array, /*alias=*/true})
|
||||
<< ".\n";
|
||||
}
|
||||
{
|
||||
Json_string string;
|
||||
std::cout << "8.3. Type of string is "
|
||||
<< json_type_name(Json_wrapper{&string, /*alias=*/true})
|
||||
<< ".\n";
|
||||
}
|
||||
{
|
||||
Json_opaque blob{MYSQL_TYPE_BLOB};
|
||||
std::cout << "8.4. Type of blob is "
|
||||
<< json_type_name(Json_wrapper{&blob, /*alias=*/true}) << ".\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure coerce_* functions are visible.
|
||||
{
|
||||
{
|
||||
Json_wrapper jw = Json_wrapper(
|
||||
create_dom_ptr<Json_string>("2015-01-15 23:24:25.000000"));
|
||||
MYSQL_TIME ltime;
|
||||
bool res = jw.coerce_date(
|
||||
[](const char *, int) { std::cout << "9.1. ERROR \n"; },
|
||||
[](MYSQL_TIME_STATUS &) { std::cout << "9.1. checking \n"; }, <ime);
|
||||
std::cout << "9.1. 2015-01-15 23:24:25.000000 is" << (res ? " NOT " : " ")
|
||||
<< "a valid DATE \n";
|
||||
}
|
||||
{
|
||||
Json_wrapper jw = Json_wrapper(
|
||||
create_dom_ptr<Json_string>("2015-99-15 23:24:25.000000"));
|
||||
MYSQL_TIME ltime;
|
||||
bool res = jw.coerce_date(
|
||||
[](const char *, int) { std::cout << "9.2. ERROR \n"; },
|
||||
[](MYSQL_TIME_STATUS &) { std::cout << "9.2. checking \n"; }, <ime);
|
||||
std::cout << "9.2. 2015-99-15 23:24:25.000000 is" << (res ? " NOT " : " ")
|
||||
<< "a valid DATE \n";
|
||||
}
|
||||
{
|
||||
Json_wrapper jw = Json_wrapper(
|
||||
create_dom_ptr<Json_string>("2015-99-15 23:24:25.000000"));
|
||||
double res = jw.coerce_real(
|
||||
[](const char *, int) { std::cout << "9.3. ERROR \n"; });
|
||||
std::cout << "9.3. 2015-99-15 23:24:25.000000 coerced to DOUBLE is "
|
||||
<< res << "\n";
|
||||
}
|
||||
{
|
||||
Json_wrapper jw =
|
||||
Json_wrapper(create_dom_ptr<Json_string>("1988.9999999"));
|
||||
my_decimal dec;
|
||||
jw.coerce_decimal([](const char *, int) { std::cout << "9.4. ERROR \n"; },
|
||||
&dec);
|
||||
int len = 128;
|
||||
const std::unique_ptr<char[]> buff(new char[len]{'\0'});
|
||||
decimal2string(&dec, buff.get(), &len);
|
||||
std::cout << "9.4. 1988.9999999 coerced to DECIMAL is " << buff << "\n";
|
||||
}
|
||||
{
|
||||
Json_wrapper jw = Json_wrapper(create_dom_ptr<Json_string>("1988"));
|
||||
double res = jw.coerce_int(
|
||||
[](const char *, int) { std::cout << "9.5. ERROR \n"; });
|
||||
std::cout << "9.5. 1988 coerced to INTEGER is " << res << "\n";
|
||||
}
|
||||
{
|
||||
Json_wrapper jw = Json_wrapper(
|
||||
create_dom_ptr<Json_string>("2015-01-15 23:24:25.000000"));
|
||||
MYSQL_TIME ltime;
|
||||
bool res = jw.coerce_time(
|
||||
[](const char *, int) { std::cout << "9.6. ERROR \n"; },
|
||||
[](MYSQL_TIME_STATUS &) { std::cout << "9.6. checking \n"; }, <ime);
|
||||
std::cout << "9.6. 2023-12-11 09:23:00.360900 is" << (res ? " NOT " : " ")
|
||||
<< "a valid TIME \n";
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
61
client/logger.cc
Normal file
61
client/logger.cc
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Copyright (c) 2015, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "client/logger.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
|
||||
ostream &operator<<(ostream &os, const Datetime &) {
|
||||
const char format[] = "%Y-%m-%d %X";
|
||||
const time_t t(time(nullptr));
|
||||
const tm tm(*localtime(&t));
|
||||
|
||||
const size_t date_length{50};
|
||||
const std::unique_ptr<char[]> date{new char[date_length]};
|
||||
strftime(date.get(), date_length, format, &tm);
|
||||
|
||||
os << date.get() << " ";
|
||||
return os;
|
||||
}
|
||||
|
||||
ostream &operator<<(ostream &os, const Gen_spaces &gen) {
|
||||
return os << gen.m_spaces;
|
||||
}
|
||||
|
||||
int Log::Log_buff::sync() {
|
||||
const string sout(str());
|
||||
if (m_enabled && sout.length() > 0) {
|
||||
m_os << Datetime() << "[" << m_logc << "]"
|
||||
<< Gen_spaces(8 - m_logc.length()) << sout;
|
||||
}
|
||||
str("");
|
||||
m_os.flush();
|
||||
return 0;
|
||||
}
|
76
client/logger.h
Normal file
76
client/logger.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
#ifndef LOGGER_UTIL_INCLUDED
|
||||
#define LOGGER_UTIL_INCLUDED
|
||||
/*
|
||||
Copyright (c) 2015, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
struct Datetime {};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Datetime &dt);
|
||||
|
||||
class Gen_spaces {
|
||||
public:
|
||||
explicit Gen_spaces(int s) { m_spaces.assign(s, ' '); }
|
||||
std::ostream &operator<<(std::ostream &os) { return os; }
|
||||
friend std::ostream &operator<<(std::ostream &os, const Gen_spaces &gen);
|
||||
|
||||
private:
|
||||
std::string m_spaces;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Gen_spaces &gen);
|
||||
|
||||
class Log : public std::ostream {
|
||||
public:
|
||||
Log(std::ostream &str, std::string logclass)
|
||||
: std::ostream(nullptr), m_buffer(str, logclass) {
|
||||
this->init(&m_buffer);
|
||||
}
|
||||
void enabled(bool s) { m_buffer.enabled(s); }
|
||||
|
||||
private:
|
||||
class Log_buff : public std::stringbuf {
|
||||
public:
|
||||
Log_buff(std::ostream &str, std::string &logc)
|
||||
: m_os(str), m_logc(logc), m_enabled(true) {}
|
||||
void set_log_class(std::string &s) { m_logc = s; }
|
||||
void enabled(bool s) { m_enabled = s; }
|
||||
bool is_enabled() { return m_enabled; }
|
||||
int sync() override;
|
||||
|
||||
private:
|
||||
std::ostream &m_os;
|
||||
std::string m_logc;
|
||||
bool m_enabled;
|
||||
};
|
||||
|
||||
Log_buff m_buffer;
|
||||
};
|
||||
|
||||
#endif /* LOGGER_UTIL_INCLUDED */
|
51
client/migrate_keyring/CMakeLists.txt
Normal file
51
client/migrate_keyring/CMakeLists.txt
Normal file
|
@ -0,0 +1,51 @@
|
|||
# Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
ADD_WSHADOW_WARNING()
|
||||
|
||||
SET(MIGRATE_KEYRING_SOURCE
|
||||
# Logger
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../logger.cc
|
||||
|
||||
# Options handling
|
||||
options.cc
|
||||
|
||||
# Components subsystem
|
||||
components.cc
|
||||
|
||||
# Main
|
||||
migrate_keyring.cc
|
||||
)
|
||||
|
||||
SET(MIGRATE_KEYRING_LIBRARIES
|
||||
${CMAKE_DL_LIBS}
|
||||
minchassis
|
||||
mysys
|
||||
mysqlclient
|
||||
OpenSSL::SSL OpenSSL::Crypto
|
||||
)
|
||||
|
||||
MYSQL_ADD_EXECUTABLE(mysql_migrate_keyring
|
||||
${MIGRATE_KEYRING_SOURCE}
|
||||
LINK_LIBRARIES ${MIGRATE_KEYRING_LIBRARIES}
|
||||
)
|
382
client/migrate_keyring/components.cc
Normal file
382
client/migrate_keyring/components.cc
Normal file
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <scope_guard.h>
|
||||
|
||||
#include "components.h"
|
||||
#include "options.h" /* command line options */
|
||||
#include "utilities.h" /* Error logging */
|
||||
|
||||
using options::Options;
|
||||
|
||||
namespace components {
|
||||
|
||||
registry_type_t *components_registry = nullptr;
|
||||
dynamic_loader_type_t *components_dynamic_loader = nullptr;
|
||||
|
||||
void init_components_subsystem() {
|
||||
minimal_chassis_init((&components_registry), nullptr);
|
||||
components_registry->acquire(
|
||||
"dynamic_loader",
|
||||
reinterpret_cast<my_h_service *>(&components_dynamic_loader));
|
||||
}
|
||||
|
||||
void deinit_components_subsystem() {
|
||||
components_registry->release(
|
||||
reinterpret_cast<my_h_service>(components_dynamic_loader));
|
||||
minimal_chassis_deinit(components_registry, nullptr);
|
||||
}
|
||||
|
||||
Keyring_component_load::Keyring_component_load(const std::string component_name,
|
||||
const std::string type)
|
||||
: dynamic_loader_(components_dynamic_loader),
|
||||
component_path_("file://"),
|
||||
type_(type) {
|
||||
if (Options::s_component_dir != nullptr)
|
||||
component_path_.append(Options::s_component_dir);
|
||||
component_path_ += "/" + component_name;
|
||||
|
||||
log_debug << "Loading: " << component_path_ << std::endl;
|
||||
|
||||
const char *urn[] = {component_path_.c_str()};
|
||||
const bool load_status = dynamic_loader_->load(urn, 1);
|
||||
if (load_status)
|
||||
log_error << "Failed to load " << type_ << " keyring: " << component_path_
|
||||
<< std::endl;
|
||||
else
|
||||
log_debug << "Successfully loaded " << type_
|
||||
<< " keyring: " << component_path_ << std::endl;
|
||||
ok_ = !load_status;
|
||||
}
|
||||
|
||||
Keyring_component_load::~Keyring_component_load() {
|
||||
if (ok_) {
|
||||
const char *urn[] = {component_path_.c_str()};
|
||||
log_debug << "Unloading: " << component_path_ << std::endl;
|
||||
const bool load_status = dynamic_loader_->unload(urn, 1);
|
||||
if (load_status)
|
||||
log_error << "Failed to unload " << type_
|
||||
<< " keyring: " << component_path_ << std::endl;
|
||||
else
|
||||
log_debug << "Successfully unloaded " << type_
|
||||
<< " keyring: " << component_path_ << std::endl;
|
||||
ok_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
Keyring_services::Keyring_services(const std::string implementation_name,
|
||||
const std::string instance_path)
|
||||
: registry_(components_registry),
|
||||
implementation_name_(implementation_name),
|
||||
keyring_load_service_(
|
||||
std::string{"keyring_load."}.append(implementation_name).c_str(),
|
||||
registry_),
|
||||
ok_(false) {
|
||||
if (keyring_load_service_) {
|
||||
log_error << "Failed to acquire keyring_load service" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (keyring_load_service_->load(
|
||||
Options::s_component_dir,
|
||||
instance_path.length() ? instance_path.c_str() : nullptr) != 0) {
|
||||
const std::string message("Failed to initialize keyring");
|
||||
log_error << message << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug << "Successfully acquired keyring error service handles for "
|
||||
<< implementation_name_ << std::endl;
|
||||
|
||||
ok_ = true;
|
||||
}
|
||||
|
||||
Keyring_services::~Keyring_services() {
|
||||
ok_ = false;
|
||||
if (!registry_) return;
|
||||
|
||||
log_debug << "Successfully released keyring error service handles for "
|
||||
<< implementation_name_ << std::endl;
|
||||
}
|
||||
|
||||
Source_keyring_services::Source_keyring_services(
|
||||
const std::string implementation_name, const std::string instance_path)
|
||||
: Keyring_services(implementation_name, instance_path),
|
||||
keyring_keys_metadata_service_("keyring_keys_metadata_iterator",
|
||||
keyring_load_service_, registry_),
|
||||
keyring_reader_service_("keyring_reader_with_status",
|
||||
keyring_load_service_, registry_) {
|
||||
if (keyring_keys_metadata_service_ || keyring_reader_service_) {
|
||||
log_error << "Failed to acquire keyring metadata iterator and keyring "
|
||||
"reader services for "
|
||||
<< implementation_name_ << std::endl;
|
||||
ok_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug << "Successfully acquired keyring metarata iterator and kering "
|
||||
"reader services' handles for "
|
||||
<< implementation_name_ << std::endl;
|
||||
}
|
||||
|
||||
Source_keyring_services::~Source_keyring_services() {
|
||||
if (registry_ == nullptr) return;
|
||||
|
||||
log_debug << "Successfully released keyring metadata iterator and reader "
|
||||
"service handles for "
|
||||
<< implementation_name_ << std::endl;
|
||||
}
|
||||
|
||||
Destination_keyring_services::Destination_keyring_services(
|
||||
const std::string implementation_name, const std::string instance_path)
|
||||
: Keyring_services(implementation_name, instance_path),
|
||||
keyring_writer_service_("keyring_writer", keyring_load_service_,
|
||||
registry_) {
|
||||
if (keyring_writer_service_) {
|
||||
log_error << "Failed to acquire keyring writer service handle for "
|
||||
<< implementation_name_ << std::endl;
|
||||
ok_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug << "Successfully acquired keyring writer service handle for "
|
||||
<< implementation_name_ << std::endl;
|
||||
}
|
||||
|
||||
Destination_keyring_services::~Destination_keyring_services() {
|
||||
if (!registry_) return;
|
||||
|
||||
log_debug << "Successfully released keyring writer service handle for "
|
||||
<< implementation_name_ << std::endl;
|
||||
}
|
||||
|
||||
Keyring_migrate::Keyring_migrate(Source_keyring_services &src,
|
||||
Destination_keyring_services &dst,
|
||||
bool online_migration)
|
||||
: src_(src), dst_(dst), mysql_connection_(online_migration) {
|
||||
if (!src_.ok() || !dst_.ok()) return;
|
||||
if (online_migration && !mysql_connection_.ok()) return;
|
||||
if (lock_source_keyring() == false) {
|
||||
log_error << "Failed to lock source keyring" << std::endl;
|
||||
return;
|
||||
}
|
||||
auto iterator = src_.metadata_iterator();
|
||||
if (iterator->init(&iterator_) != 0) {
|
||||
log_error << "Error creating source keyring iterator" << std::endl;
|
||||
return;
|
||||
}
|
||||
ok_ = true;
|
||||
}
|
||||
|
||||
bool Keyring_migrate::lock_source_keyring() {
|
||||
if (Options::s_online_migration == false) return true;
|
||||
if (!mysql_connection_.ok()) return false;
|
||||
const std::string lock_statement("SET GLOBAL KEYRING_OPERATIONS=0");
|
||||
return mysql_connection_.execute(lock_statement);
|
||||
}
|
||||
|
||||
bool Keyring_migrate::unlock_source_keyring() {
|
||||
if (Options::s_online_migration == false || !mysql_connection_.ok())
|
||||
return true;
|
||||
const std::string unlock_statement("SET GLOBAL KEYRING_OPERATIONS=1");
|
||||
return mysql_connection_.execute(unlock_statement);
|
||||
}
|
||||
|
||||
bool Keyring_migrate::migrate_keys() {
|
||||
if (!ok_)
|
||||
log_error << "Cannot migrate keys. Check that source and destination "
|
||||
"keyrings are initialized properly."
|
||||
<< std::endl;
|
||||
|
||||
auto metadata_iterator = src_.metadata_iterator();
|
||||
auto reader = src_.reader();
|
||||
auto writer = dst_.writer();
|
||||
size_t migrated_count = 0;
|
||||
size_t skipped_count = 0;
|
||||
bool retval = true;
|
||||
bool next_ok = true;
|
||||
|
||||
size_t data_id_length = 0;
|
||||
size_t auth_id_length = 0;
|
||||
|
||||
for (; metadata_iterator->is_valid(iterator_) && next_ok;
|
||||
next_ok = !metadata_iterator->next(iterator_)) {
|
||||
data_id_length = 0;
|
||||
auth_id_length = 0;
|
||||
/* Fetch length */
|
||||
if (metadata_iterator->get_length(iterator_, &data_id_length,
|
||||
&auth_id_length) != 0) {
|
||||
log_error << "Could not fetch next available key content from keyring"
|
||||
<< std::endl;
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
|
||||
const std::unique_ptr<char[]> data_id(new char[data_id_length + 1]);
|
||||
const std::unique_ptr<char[]> auth_id(new char[auth_id_length + 1]);
|
||||
|
||||
if (data_id.get() == nullptr || auth_id.get() == nullptr) {
|
||||
log_error << "Failed to allocated required memory for data_id and auth_id"
|
||||
<< std::endl;
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
/* Fetch metadata of next available key */
|
||||
if (metadata_iterator->get(iterator_, data_id.get(), data_id_length + 1,
|
||||
auth_id.get(), auth_id_length + 1) != 0) {
|
||||
log_error << "Could not fetch next available key content from keyring"
|
||||
<< std::endl;
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fetch key details */
|
||||
my_h_keyring_reader_object reader_object = nullptr;
|
||||
const bool status =
|
||||
reader->init(data_id.get(), auth_id.get(), &reader_object);
|
||||
|
||||
if (status == true) {
|
||||
log_error << "Keyring reported error" << std::endl;
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (reader_object == nullptr) {
|
||||
log_warning << "Could not find data pointed by data_id: " << data_id.get()
|
||||
<< ", auth_id: " << auth_id.get() << ". Skipping"
|
||||
<< std::endl;
|
||||
++skipped_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto cleanup_guard = create_scope_guard([&] {
|
||||
if (reader_object != nullptr) {
|
||||
if (reader->deinit(reader_object) != 0)
|
||||
log_error << "Failed to deallocated reader_object" << std::endl;
|
||||
}
|
||||
reader_object = nullptr;
|
||||
});
|
||||
|
||||
size_t data_size, data_type_size;
|
||||
if (reader->fetch_length(reader_object, &data_size, &data_type_size) != 0) {
|
||||
log_warning << "Could not find data pointed by data_id: " << data_id.get()
|
||||
<< ", auth_id: " << auth_id.get() << ". Skipping"
|
||||
<< std::endl;
|
||||
++skipped_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data_size > maximum_size_) {
|
||||
log_warning << "Length (" << data_size
|
||||
<< ") of data identified by data_id: " << data_id.get()
|
||||
<< ", auth_id: " << auth_id.get()
|
||||
<< " exceeds maximum supported"
|
||||
" length by migration tool ("
|
||||
<< maximum_size_ << "). Skipping" << std::endl;
|
||||
++skipped_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::unique_ptr<unsigned char[]> data_buffer(
|
||||
new unsigned char[data_size]);
|
||||
const std::unique_ptr<char[]> data_type_buffer(
|
||||
new char[data_type_size + 1]);
|
||||
|
||||
if (data_buffer.get() == nullptr || data_type_buffer.get() == nullptr) {
|
||||
log_error << "Failed to allocated required memory for data pointed by "
|
||||
"data_id: "
|
||||
<< data_id.get() << ", auth_id: " << auth_id.get()
|
||||
<< ". Stopping." << std::endl;
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(data_buffer.get(), 0, data_size);
|
||||
memset(data_type_buffer.get(), 0, data_type_size + 1);
|
||||
|
||||
if (reader->fetch(reader_object, data_buffer.get(), data_size, &data_size,
|
||||
data_type_buffer.get(), data_type_size + 1,
|
||||
&data_type_size) != 0) {
|
||||
log_warning << "Could not find data pointed by data_id: " << data_id.get()
|
||||
<< ", auth_id: " << auth_id.get() << ". Skipping"
|
||||
<< std::endl;
|
||||
++skipped_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Write to destination keyring */
|
||||
if (data_size > 0 && data_type_size > 0) {
|
||||
const bool write_status =
|
||||
writer->store(data_id.get(), auth_id.get(), data_buffer.get(),
|
||||
data_size, data_type_buffer.get());
|
||||
memset(data_buffer.get(), 0, data_size);
|
||||
memset(data_type_buffer.get(), 0, data_type_size + 1);
|
||||
if (write_status == true) {
|
||||
log_error << "Failed to write data pointed by data_id: "
|
||||
<< data_id.get() << ", auth_id: " << auth_id.get()
|
||||
<< " into destination keyring" << std::endl;
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
log_debug << "Successfully migrated data with data_id: " << data_id.get()
|
||||
<< ", auth_id: " << auth_id.get() << "." << std::endl;
|
||||
}
|
||||
|
||||
++migrated_count;
|
||||
}
|
||||
|
||||
if (metadata_iterator->deinit(iterator_) != 0) {
|
||||
log_error << "Failed to deinitialize source iterator" << std::endl;
|
||||
retval = false;
|
||||
}
|
||||
iterator_ = nullptr;
|
||||
|
||||
if (retval) {
|
||||
log_info << "Successfully migrated " << migrated_count << " keys. Skipped "
|
||||
<< skipped_count << " keys." << std::endl;
|
||||
} else {
|
||||
log_error << "Failed to migrate all keys to destination keyring. Please "
|
||||
"check log for more details"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Keyring_migrate::~Keyring_migrate() {
|
||||
if (unlock_source_keyring() == false) {
|
||||
log_error << "Failed to unlock source keyring. Please unlock it manually."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace components
|
149
client/migrate_keyring/components.h
Normal file
149
client/migrate_keyring/components.h
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef COMPONENTS_INCLUDED
|
||||
#define COMPONENTS_INCLUDED
|
||||
|
||||
#include <mysql/components/minimal_chassis.h> /* Minimal chassis */
|
||||
#include <mysql/components/my_service.h>
|
||||
#include <mysql/components/services/keyring_keys_metadata_iterator.h>
|
||||
#include <mysql/components/services/keyring_load.h>
|
||||
#include <mysql/components/services/keyring_reader_with_status.h>
|
||||
#include <mysql/components/services/keyring_writer.h>
|
||||
|
||||
#include "client/logger.h" /* Log */
|
||||
#include "options.h" /* Mysql_connection */
|
||||
namespace components {
|
||||
using registry_type_t = SERVICE_TYPE_NO_CONST(registry);
|
||||
using dynamic_loader_type_t = SERVICE_TYPE_NO_CONST(dynamic_loader);
|
||||
using keyring_load_t = SERVICE_TYPE_NO_CONST(keyring_load);
|
||||
using keyring_keys_metadata_iterator_t =
|
||||
SERVICE_TYPE_NO_CONST(keyring_keys_metadata_iterator);
|
||||
using keyring_reader_with_status_t =
|
||||
SERVICE_TYPE_NO_CONST(keyring_reader_with_status);
|
||||
using keyring_writer_t = SERVICE_TYPE_NO_CONST(keyring_writer);
|
||||
|
||||
using const_registry_type_t = SERVICE_TYPE(registry);
|
||||
using const_dynamic_loader_type_t = SERVICE_TYPE(dynamic_loader);
|
||||
using const_keyring_keys_metadata_iterator_t =
|
||||
SERVICE_TYPE(keyring_keys_metadata_iterator);
|
||||
using const_keyring_load_t = SERVICE_TYPE(keyring_load);
|
||||
using const_keyring_reader_with_status_t =
|
||||
SERVICE_TYPE(keyring_reader_with_status);
|
||||
using const_keyring_writer_t = SERVICE_TYPE(keyring_writer);
|
||||
|
||||
void init_components_subsystem();
|
||||
void deinit_components_subsystem();
|
||||
|
||||
class Keyring_component_load final {
|
||||
public:
|
||||
Keyring_component_load(const std::string component_name,
|
||||
const std::string type);
|
||||
|
||||
~Keyring_component_load();
|
||||
|
||||
bool ok() { return ok_; }
|
||||
|
||||
private:
|
||||
dynamic_loader_type_t *dynamic_loader_;
|
||||
std::string component_path_;
|
||||
std::string type_;
|
||||
bool ok_;
|
||||
};
|
||||
|
||||
class Keyring_services {
|
||||
public:
|
||||
Keyring_services(const std::string implementation_name,
|
||||
const std::string instance_path);
|
||||
|
||||
virtual ~Keyring_services();
|
||||
|
||||
bool ok() { return ok_; }
|
||||
|
||||
protected:
|
||||
registry_type_t *registry_;
|
||||
std::string implementation_name_;
|
||||
my_service<const_keyring_load_t> keyring_load_service_;
|
||||
bool ok_;
|
||||
};
|
||||
|
||||
class Source_keyring_services final : public Keyring_services {
|
||||
public:
|
||||
Source_keyring_services(const std::string implementation_name,
|
||||
const std::string instance_path);
|
||||
|
||||
~Source_keyring_services();
|
||||
|
||||
const_keyring_keys_metadata_iterator_t *metadata_iterator() {
|
||||
return keyring_keys_metadata_service_;
|
||||
}
|
||||
const_keyring_reader_with_status_t *reader() {
|
||||
return keyring_reader_service_;
|
||||
}
|
||||
|
||||
private:
|
||||
my_service<const_keyring_keys_metadata_iterator_t>
|
||||
keyring_keys_metadata_service_;
|
||||
my_service<const_keyring_reader_with_status_t> keyring_reader_service_;
|
||||
};
|
||||
|
||||
class Destination_keyring_services final : public Keyring_services {
|
||||
public:
|
||||
Destination_keyring_services(const std::string implementation_name,
|
||||
const std::string instance_path);
|
||||
|
||||
~Destination_keyring_services();
|
||||
|
||||
const_keyring_writer_t *writer() { return keyring_writer_service_; }
|
||||
|
||||
private:
|
||||
my_service<const_keyring_writer_t> keyring_writer_service_;
|
||||
};
|
||||
|
||||
class Keyring_migrate final {
|
||||
public:
|
||||
Keyring_migrate(Source_keyring_services &src,
|
||||
Destination_keyring_services &dst, bool online_migration);
|
||||
|
||||
bool migrate_keys();
|
||||
|
||||
~Keyring_migrate();
|
||||
|
||||
bool lock_source_keyring();
|
||||
bool unlock_source_keyring();
|
||||
bool ok() { return ok_; }
|
||||
|
||||
private:
|
||||
Source_keyring_services &src_;
|
||||
Destination_keyring_services &dst_;
|
||||
my_h_keyring_keys_metadata_iterator iterator_{nullptr};
|
||||
options::Mysql_connection mysql_connection_;
|
||||
bool ok_{false};
|
||||
const size_t maximum_size_{16384};
|
||||
};
|
||||
|
||||
} // namespace components
|
||||
|
||||
#endif // !COMPONENTS_INCLUDED
|
146
client/migrate_keyring/migrate_keyring.cc
Normal file
146
client/migrate_keyring/migrate_keyring.cc
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
/* <openssl/applink.c> is included in client library */
|
||||
|
||||
#include <my_dbug.h> /* DEBUG macros */
|
||||
#include <my_sys.h> /* MY_INIT */
|
||||
#include <scope_guard.h>
|
||||
|
||||
#include "components.h"
|
||||
#include "options.h"
|
||||
#include "utilities.h"
|
||||
|
||||
using components::deinit_components_subsystem;
|
||||
using components::Destination_keyring_services;
|
||||
using components::init_components_subsystem;
|
||||
using components::Keyring_component_load;
|
||||
using components::Keyring_migrate;
|
||||
using components::Source_keyring_services;
|
||||
|
||||
using options::deinit_connection_basic;
|
||||
using options::init_connection_basic;
|
||||
using options::Options;
|
||||
using options::process_options;
|
||||
|
||||
Log log_debug(std::cout, "DEBUG");
|
||||
Log log_info(std::cout, "NOTE");
|
||||
Log log_warning(std::cerr, "WARNING");
|
||||
Log log_error(std::cerr, "ERROR");
|
||||
|
||||
class Migration_setup {
|
||||
public:
|
||||
explicit Migration_setup(char *progname) {
|
||||
MY_INIT(progname);
|
||||
init_components_subsystem();
|
||||
init_connection_basic();
|
||||
log_debug.enabled(false);
|
||||
}
|
||||
|
||||
~Migration_setup() {
|
||||
deinit_connection_basic();
|
||||
deinit_components_subsystem();
|
||||
my_end(0);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
/* Initialization */
|
||||
const Migration_setup migration_setup(argv[0]);
|
||||
DBUG_TRACE;
|
||||
DBUG_PROCESS(argv[0]);
|
||||
const int exit_status = EXIT_FAILURE;
|
||||
|
||||
int exit_code;
|
||||
if (process_options(&argc, &argv, exit_code) == false) {
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
{
|
||||
Keyring_component_load source_component_load(Options::s_source_keyring,
|
||||
"source");
|
||||
|
||||
if (!source_component_load.ok()) {
|
||||
log_error << "Error loading source keyring component. Exiting."
|
||||
<< std::endl;
|
||||
return exit_status;
|
||||
}
|
||||
Keyring_component_load destination_component_load(
|
||||
Options::s_destination_keyring, "destination");
|
||||
|
||||
if (!destination_component_load.ok()) {
|
||||
log_error << "Error loading destination keyring component. Exiting."
|
||||
<< std::endl;
|
||||
return exit_status;
|
||||
}
|
||||
Source_keyring_services source_service(
|
||||
Options::s_source_keyring,
|
||||
Options::s_source_keyring_configuration_dir
|
||||
? Options::s_source_keyring_configuration_dir
|
||||
: "");
|
||||
if (!source_service.ok()) {
|
||||
log_error << "Failed to load required services from source keyring. "
|
||||
"Exiting."
|
||||
<< std::endl;
|
||||
return exit_status;
|
||||
}
|
||||
Destination_keyring_services destination_service(
|
||||
Options::s_destination_keyring,
|
||||
Options::s_destination_keyring_configuration_dir != nullptr
|
||||
? Options::s_destination_keyring_configuration_dir
|
||||
: "");
|
||||
|
||||
if (!destination_service.ok()) {
|
||||
log_error << "Failed to load required services from destination "
|
||||
"keyring. Exiting."
|
||||
<< std::endl;
|
||||
return exit_status;
|
||||
}
|
||||
Keyring_migrate keyring_migrate(source_service, destination_service,
|
||||
Options::s_online_migration);
|
||||
if (!keyring_migrate.ok()) {
|
||||
log_error << "Error migrating keys from: " << Options::s_source_keyring
|
||||
<< " to: " << Options::s_destination_keyring
|
||||
<< ". See log for more details" << std::endl;
|
||||
return exit_status;
|
||||
}
|
||||
log_info << "Successfully loaded source and destination "
|
||||
"keyrings. Initiating migration."
|
||||
<< std::endl;
|
||||
if (!keyring_migrate.migrate_keys()) {
|
||||
log_error << "Error migrating keys from: " << Options::s_source_keyring
|
||||
<< " to: " << Options::s_destination_keyring
|
||||
<< ". See log for more details" << std::endl;
|
||||
return exit_status;
|
||||
}
|
||||
log_info << "Key migration successful." << std::endl;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
380
client/migrate_keyring/options.cc
Normal file
380
client/migrate_keyring/options.cc
Normal file
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <my_alloc.h> /* MEM_ROOT */
|
||||
#include <my_default.h> /* print_defaults */
|
||||
#include <my_getopt.h> /* Options handling */
|
||||
#include <my_inttypes.h> /* typedefs */
|
||||
#include <my_macros.h> /* STRINGIFY_ARG */
|
||||
#include <mysql.h> /* MYSQL */
|
||||
#include <mysql/service_mysql_alloc.h>/* my_strdup */
|
||||
#include <mysql_com.h> /* get_tty_password */
|
||||
#include <print_version.h> /* print_version */
|
||||
#include <typelib.h> /* find_type_or_exit */
|
||||
#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
|
||||
#include "m_string.h"
|
||||
#include "mysql/strings/m_ctype.h" /* Character set */
|
||||
#include "nulls.h"
|
||||
#include "template_utils.h"
|
||||
|
||||
#include "options.h"
|
||||
#include "utilities.h"
|
||||
|
||||
/* TLS variables */
|
||||
#include "client/include/sslopt-vars.h"
|
||||
|
||||
namespace options {
|
||||
|
||||
/** MEM_ROOT for arguments */
|
||||
static MEM_ROOT argv_alloc{PSI_NOT_INSTRUMENTED, 512};
|
||||
|
||||
enum migration_options {
|
||||
OPT_COMPONENT_DIR = 512,
|
||||
OPT_SOURCE_KEYRING,
|
||||
OPT_SOURCE_KEYRING_CONFIG_DIR,
|
||||
OPT_DESTINATION_KEYRING,
|
||||
OPT_DESTINATION_KEYRING_CONFIG_DIR,
|
||||
OPT_ONLINE_MIGRATION,
|
||||
OPT_SSL_MODE,
|
||||
OPT_SSL_CA,
|
||||
OPT_SSL_CAPATH,
|
||||
OPT_SSL_CERT,
|
||||
OPT_SSL_CIPHER,
|
||||
OPT_SSL_KEY,
|
||||
OPT_SSL_CRL,
|
||||
OPT_SSL_CRLPATH,
|
||||
OPT_TLS_VERSION,
|
||||
OPT_SSL_FIPS_MODE,
|
||||
OPT_TLS_CIPHERSUITES,
|
||||
OPT_SERVER_PUBLIC_KEY,
|
||||
OPT_SSL_SESSION_DATA,
|
||||
OPT_SSL_SESSION_DATA_CONTINUE_ON_FAILED_REUSE,
|
||||
OPT_TLS_SNI_SERVERNAME,
|
||||
/* Add new value above this */
|
||||
OPT_LAST
|
||||
};
|
||||
|
||||
bool Options::s_help = false;
|
||||
bool Options::s_verbose = false;
|
||||
char *Options::s_component_dir = nullptr;
|
||||
char *Options::s_source_keyring = nullptr;
|
||||
char *Options::s_source_keyring_configuration_dir = nullptr;
|
||||
char *Options::s_destination_keyring = nullptr;
|
||||
char *Options::s_destination_keyring_configuration_dir = nullptr;
|
||||
bool Options::s_online_migration = false;
|
||||
char *Options::s_hostname = nullptr;
|
||||
unsigned int Options::s_port = 0;
|
||||
char *Options::s_username = nullptr;
|
||||
char *Options::s_password = nullptr;
|
||||
char *Options::s_socket = nullptr;
|
||||
bool Options::s_tty_password = false;
|
||||
|
||||
/* Caching sha2 password variables */
|
||||
#include "client/include/caching_sha2_passwordopt-vars.h"
|
||||
|
||||
/** Options group */
|
||||
static const char *load_default_groups[] = {"mysql_migrate_keyring", nullptr};
|
||||
|
||||
/** Command line options */
|
||||
static struct my_option my_long_options[] = {
|
||||
{"help", '?', "Display this help and exit.", nullptr, nullptr, nullptr,
|
||||
GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"version", 'V', "Output version information and exit.", nullptr, nullptr,
|
||||
nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"component_dir", OPT_COMPONENT_DIR, "Directory for components/plugins.",
|
||||
&Options::s_component_dir, &Options::s_component_dir, nullptr, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"source_keyring", OPT_SOURCE_KEYRING,
|
||||
"Source keyring name (without extension)", &Options::s_source_keyring,
|
||||
&Options::s_source_keyring, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"source_keyring_configuration_dir", OPT_SOURCE_KEYRING_CONFIG_DIR,
|
||||
"Source keyring configuration directory",
|
||||
&Options::s_source_keyring_configuration_dir,
|
||||
&Options::s_source_keyring_configuration_dir, nullptr, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"destination_keyring", OPT_DESTINATION_KEYRING,
|
||||
"Destination keyring component name (without extension)",
|
||||
&Options::s_destination_keyring, &Options::s_destination_keyring, nullptr,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"destination_keyring_configuration_dir",
|
||||
OPT_DESTINATION_KEYRING_CONFIG_DIR,
|
||||
"Destination keyring configuration directory",
|
||||
&Options::s_destination_keyring_configuration_dir,
|
||||
&Options::s_destination_keyring_configuration_dir, nullptr, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"online_migration", OPT_ONLINE_MIGRATION,
|
||||
"Signal the utility that source of migration is an active server",
|
||||
&Options::s_online_migration, &Options::s_online_migration, nullptr,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"host", 'h', "Connect to host.", &Options::s_hostname,
|
||||
&Options::s_hostname, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"port", 'P',
|
||||
"Port number to use for connection or 0 for default to, in "
|
||||
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
|
||||
#if MYSQL_PORT_DEFAULT == 0
|
||||
"/etc/services, "
|
||||
#endif
|
||||
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
|
||||
&Options::s_port, &Options::s_port, nullptr, GET_UINT, REQUIRED_ARG, 0, 0,
|
||||
0, nullptr, 0, nullptr},
|
||||
#ifndef _WIN32
|
||||
{"socket", 'S', "The socket file to use for connection.",
|
||||
&Options::s_socket, &Options::s_socket, nullptr, GET_STR_ALLOC,
|
||||
REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#endif // _WIN32
|
||||
{"user", 'u', "User for login if not current user.", &Options::s_username,
|
||||
&Options::s_username, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"password", 'p',
|
||||
"Password to use when connecting to server. If password is not given it's "
|
||||
"asked from the tty.",
|
||||
nullptr, nullptr, nullptr, GET_PASSWORD, OPT_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
/* TLS options */
|
||||
#include "client/include/sslopt-longopts.h"
|
||||
/* Caching sha2 password options */
|
||||
#include "client/include/caching_sha2_passwordopt-longopts.h"
|
||||
{"verbose", 'v', "Write more.", nullptr, nullptr, nullptr, GET_NO_ARG,
|
||||
NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
/* Must be the last one */
|
||||
{nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
|
||||
0, nullptr, 0, nullptr}};
|
||||
|
||||
static void usage(bool version_only) {
|
||||
print_version();
|
||||
if (version_only) return;
|
||||
std::cout << ORACLE_WELCOME_COPYRIGHT_NOTICE("2021") << std::endl;
|
||||
std::cout << "MySQL Keyring Migration Utility" << std::endl;
|
||||
std::cout << "Usage: " << my_progname << " [OPTIONS] " << std::endl;
|
||||
my_print_help(my_long_options);
|
||||
print_defaults("my", load_default_groups);
|
||||
my_print_variables(my_long_options);
|
||||
}
|
||||
|
||||
bool get_one_option(int optid, const struct my_option *opt, char *argument) {
|
||||
switch (optid) {
|
||||
case 'V':
|
||||
Options::s_help = true;
|
||||
usage(true);
|
||||
break;
|
||||
case 'I':
|
||||
[[fallthrough]];
|
||||
case '?':
|
||||
Options::s_help = true;
|
||||
usage(false);
|
||||
break;
|
||||
case 'v':
|
||||
log_debug.enabled(!(argument == disabled_my_option));
|
||||
break;
|
||||
case 'p':
|
||||
if (argument == disabled_my_option) {
|
||||
// Don't require password
|
||||
static char empty_password[] = {'\0'};
|
||||
assert(empty_password[0] ==
|
||||
'\0'); // Check that it has not been overwritten
|
||||
argument = empty_password;
|
||||
}
|
||||
if (argument) {
|
||||
char *start = argument;
|
||||
my_free(Options::s_password);
|
||||
Options::s_password =
|
||||
my_strdup(PSI_NOT_INSTRUMENTED, argument, MYF(MY_FAE));
|
||||
while (*argument) *argument++ = 'x'; /* Destroy argument */
|
||||
if (*start) start[1] = 0; /* Cut length of argument */
|
||||
Options::s_tty_password = false;
|
||||
} else
|
||||
Options::s_tty_password = true;
|
||||
break;
|
||||
/* Handle TLS options */
|
||||
#include "client/include/sslopt-case.h"
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool check_options_for_sanity() {
|
||||
if (Options::s_component_dir == nullptr || !*Options::s_component_dir ||
|
||||
Options::s_source_keyring == nullptr || !*Options::s_source_keyring ||
|
||||
Options::s_destination_keyring == nullptr ||
|
||||
!*Options::s_destination_keyring) {
|
||||
log_error << "Location of components (--component-dir) and details of "
|
||||
"source (--source-keyirng) and destination "
|
||||
"(--destination-keyring) components is mandatory"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcmp(Options::s_source_keyring, Options::s_destination_keyring) == 0) {
|
||||
log_error << "Source and destination cannot be the same." << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool get_options(int argc, char **argv, int &exit_code) {
|
||||
exit_code = handle_options(&argc, &argv, my_long_options, get_one_option);
|
||||
if (exit_code != 0) {
|
||||
log_error << "Failed to parse command line arguments." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Options::s_help == true) {
|
||||
exit_code = EXIT_SUCCESS;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (check_options_for_sanity() == false) return false;
|
||||
|
||||
if (Options::s_tty_password) Options::s_password = get_tty_password(NullS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool process_options(int *argc, char ***argv, int &exit_code) {
|
||||
exit_code = 0;
|
||||
#ifdef _WIN32
|
||||
/* Convert command line parameters from UTF16LE to UTF8MB4. */
|
||||
my_win_translate_command_line_args(&my_charset_utf8mb4_bin, argc, argv);
|
||||
#endif
|
||||
|
||||
my_getopt_use_args_separator = true;
|
||||
if (load_defaults("my", load_default_groups, argc, argv, &argv_alloc)) {
|
||||
log_error << "Failed to load default options groups" << std::endl;
|
||||
return false;
|
||||
}
|
||||
my_getopt_use_args_separator = false;
|
||||
|
||||
const bool save_skip_unknown = my_getopt_skip_unknown;
|
||||
my_getopt_skip_unknown = true;
|
||||
const bool ret = get_options(*argc, *argv, exit_code);
|
||||
my_getopt_skip_unknown = save_skip_unknown;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* MYSQL Handle used to connect to an active server */
|
||||
|
||||
void init_connection_basic() {}
|
||||
void deinit_connection_basic() {
|
||||
if (Options::s_password != nullptr) {
|
||||
char *start = Options::s_password;
|
||||
while (*start) *start++ = 'x';
|
||||
my_free(Options::s_password);
|
||||
Options::s_password = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const char *default_charset = MYSQL_AUTODETECT_CHARSET_NAME;
|
||||
|
||||
Mysql_connection::Mysql_connection(bool connect) : ok_(false), mysql(nullptr) {
|
||||
if (connect == false) return;
|
||||
mysql_library_init(0, nullptr, nullptr);
|
||||
mysql = new (std::nothrow) MYSQL();
|
||||
if (mysql == nullptr) {
|
||||
log_error << "Failed to allocate memory for MYSQL structure" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (mysql_init(mysql) == nullptr) {
|
||||
log_error << " Failed to initialize MySQL connection structure"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (SSL_SET_OPTIONS(mysql) != 0) {
|
||||
log_error << "Failed to set SSL options" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
|
||||
if (Options::s_component_dir != nullptr && *Options::s_component_dir) {
|
||||
if (mysql_options(mysql, MYSQL_PLUGIN_DIR, Options::s_component_dir) != 0) {
|
||||
log_error << "Failed to set plugin directory" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, nullptr) != 0) {
|
||||
log_error << "Failed to reset connection attributes" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name",
|
||||
"mysql_migrate_keyring") != 0) {
|
||||
log_error << "Failed to add program name to connection attributes"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
set_server_public_key(mysql);
|
||||
set_get_server_public_key_option(mysql);
|
||||
|
||||
if (!mysql_real_connect(mysql, Options::s_hostname, Options::s_username,
|
||||
Options::s_password, NullS, Options::s_port,
|
||||
Options::s_socket, CLIENT_REMEMBER_OPTIONS)) {
|
||||
log_error << "Failed to connect to server. Received error: "
|
||||
<< mysql_error(mysql) << std::endl;
|
||||
return;
|
||||
}
|
||||
if (ssl_client_check_post_connect_ssl_setup(
|
||||
mysql, [](const char *err) { log_error << err << std::endl; }))
|
||||
return;
|
||||
|
||||
log_info << "Successfully connected to MySQL server" << std::endl;
|
||||
|
||||
ok_ = true;
|
||||
}
|
||||
|
||||
Mysql_connection::~Mysql_connection() {
|
||||
if (mysql != nullptr) {
|
||||
mysql_close(mysql);
|
||||
delete mysql;
|
||||
mysql = nullptr;
|
||||
}
|
||||
mysql_library_end();
|
||||
ok_ = false;
|
||||
}
|
||||
|
||||
bool Mysql_connection::execute(std::string command) {
|
||||
if (!ok_) {
|
||||
log_error << "Connection to MySQL server is not initialized." << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (mysql_real_query(mysql, command.c_str(), command.length())) {
|
||||
log_error << "Failed to execute: " << command
|
||||
<< ". Server error: " << mysql_error(mysql) << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace options
|
106
client/migrate_keyring/options.h
Normal file
106
client/migrate_keyring/options.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef OPTIONS_INCLUDED
|
||||
#define OPTIONS_INCLUDED
|
||||
|
||||
struct MYSQL;
|
||||
|
||||
namespace options {
|
||||
|
||||
/**
|
||||
Command line options container
|
||||
*/
|
||||
|
||||
class Options {
|
||||
public:
|
||||
/** Help */
|
||||
static bool s_help;
|
||||
/** Be loud */
|
||||
static bool s_verbose;
|
||||
/** Component directory location */
|
||||
static char *s_component_dir;
|
||||
/** Source keyring - Component or plugin */
|
||||
static char *s_source_keyring;
|
||||
/** Source Keyring configuration path - If it is not in component dir */
|
||||
static char *s_source_keyring_configuration_dir;
|
||||
/** Destination keyring - Must be a component */
|
||||
static char *s_destination_keyring;
|
||||
/** Destination Keyring configuration path - If it is not in component dir */
|
||||
static char *s_destination_keyring_configuration_dir;
|
||||
|
||||
/*
|
||||
Following parameters are needed if migration involves an active MySQL server
|
||||
*/
|
||||
|
||||
/** Flag for online migration */
|
||||
static bool s_online_migration;
|
||||
/** Hostname */
|
||||
static char *s_hostname;
|
||||
/** Port */
|
||||
static unsigned int s_port;
|
||||
/** Socket */
|
||||
static char *s_socket;
|
||||
/** User name */
|
||||
static char *s_username;
|
||||
/** Password */
|
||||
static char *s_password;
|
||||
/** Password to be fetched */
|
||||
static bool s_tty_password;
|
||||
};
|
||||
|
||||
/**
|
||||
Process command line options
|
||||
|
||||
@param [in, out] argc Number of arguments
|
||||
@param [in, out] argv Command line argument array
|
||||
@param [out] exit_code Exit code
|
||||
|
||||
@returns status of argument processing
|
||||
@retval true Success
|
||||
@retval false Failure
|
||||
*/
|
||||
bool process_options(int *argc, char ***argv, int &exit_code);
|
||||
|
||||
/** Initialize MYSQL connection structures */
|
||||
void init_connection_basic();
|
||||
|
||||
/** Deinitialize MYSQL connection structures */
|
||||
void deinit_connection_basic();
|
||||
|
||||
class Mysql_connection {
|
||||
public:
|
||||
explicit Mysql_connection(bool connect);
|
||||
~Mysql_connection();
|
||||
bool execute(std::string command);
|
||||
bool ok() { return ok_; }
|
||||
|
||||
private:
|
||||
bool ok_;
|
||||
MYSQL *mysql;
|
||||
};
|
||||
} // namespace options
|
||||
|
||||
#endif // !OPTIONS_INCLUDED
|
33
client/migrate_keyring/utilities.h
Normal file
33
client/migrate_keyring/utilities.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef UTILITIES_INCLUDED
|
||||
#define UTILITIES_INCLUDED
|
||||
|
||||
#include "client/logger.h" /* Logging */
|
||||
|
||||
extern Log log_debug, log_info, log_warning, log_error;
|
||||
|
||||
#endif // !UTILITIES_INCLUDED
|
103
client/multi_factor_passwordopt-vars.cc
Normal file
103
client/multi_factor_passwordopt-vars.cc
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/**
|
||||
@file include/multi_factor_passwordopt-vars.h
|
||||
*/
|
||||
|
||||
#include "client/include/multi_factor_passwordopt-vars.h"
|
||||
#include "my_getopt.h"
|
||||
#include "mysql.h"
|
||||
#include "mysql/service_mysql_alloc.h" // my_free, my_strdup
|
||||
#include "nulls.h"
|
||||
|
||||
char *opt_password[MAX_AUTH_FACTORS] = {nullptr};
|
||||
bool tty_password[MAX_AUTH_FACTORS] = {false};
|
||||
|
||||
/**
|
||||
Helper method used by clients to parse password set as part of command line.
|
||||
This method checks if password value is specified or not. If not then a flag
|
||||
is set to let client accept password from terminal.
|
||||
|
||||
@param opt password option
|
||||
@param argument value specified for --password<1,2,3> or --password
|
||||
*/
|
||||
void parse_command_line_password_option(const struct my_option *opt,
|
||||
char *argument) {
|
||||
if (argument == disabled_my_option) {
|
||||
// Don't require password
|
||||
static char empty_password[] = {'\0'};
|
||||
assert(empty_password[0] ==
|
||||
'\0'); // Check that it has not been overwritten
|
||||
argument = empty_password;
|
||||
}
|
||||
/*
|
||||
password options can be --password or --password1 or --password2 or
|
||||
--password3. Thus extract factor from option.
|
||||
*/
|
||||
unsigned int factor = 0;
|
||||
if (strcmp(opt->name, "password"))
|
||||
factor = opt->name[strlen("password")] - '0' - 1;
|
||||
if (argument) {
|
||||
char *start = argument;
|
||||
my_free(opt_password[factor]);
|
||||
opt_password[factor] =
|
||||
my_strdup(PSI_NOT_INSTRUMENTED, argument, MYF(MY_FAE));
|
||||
while (*argument) *argument++ = 'x'; // Destroy argument
|
||||
if (*start) start[1] = 0;
|
||||
tty_password[factor] = false;
|
||||
} else
|
||||
tty_password[factor] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
Helper method used by clients to set password in mysql->options
|
||||
*/
|
||||
void set_password_options(MYSQL *mysql) {
|
||||
for (unsigned int factor = 1; factor <= MAX_AUTH_FACTORS; factor++) {
|
||||
/**
|
||||
If tty_password is true get password from terminal and update in
|
||||
opt_password and set tty_password to false
|
||||
*/
|
||||
if (tty_password[factor - 1]) {
|
||||
opt_password[factor - 1] = get_tty_password(NullS);
|
||||
tty_password[factor - 1] = false;
|
||||
}
|
||||
/**
|
||||
If opt_password is populated call mysql_options4()
|
||||
*/
|
||||
if (opt_password[factor - 1]) {
|
||||
mysql_options4(mysql, MYSQL_OPT_USER_PASSWORD, &factor,
|
||||
opt_password[factor - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void free_passwords() {
|
||||
for (unsigned int factor = 1; factor <= MAX_AUTH_FACTORS; factor++) {
|
||||
if (opt_password[factor - 1]) {
|
||||
my_free(opt_password[factor - 1]);
|
||||
opt_password[factor - 1] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
52
client/multi_option.cc
Normal file
52
client/multi_option.cc
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright (c) 2012, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "multi_option.h"
|
||||
|
||||
void Multi_option::add_value(char *value, bool clear) {
|
||||
if (option_values == nullptr) {
|
||||
option_values = reinterpret_cast<Multi_option_container *>(my_malloc(
|
||||
PSI_NOT_INSTRUMENTED, sizeof(Multi_option_container), MYF(MY_WME)));
|
||||
// in a rare case when the allocation fails
|
||||
if (option_values == nullptr) return;
|
||||
new (option_values) Multi_option_container(PSI_NOT_INSTRUMENTED);
|
||||
} else if (clear)
|
||||
option_values->clear();
|
||||
option_values->emplace_back(value);
|
||||
}
|
||||
|
||||
void Multi_option::set_mysql_options(MYSQL *mysql, mysql_option option) {
|
||||
if (option_values)
|
||||
for (auto const &init_command : *option_values)
|
||||
mysql_options(mysql, option, init_command);
|
||||
}
|
||||
|
||||
void Multi_option::free() {
|
||||
if (option_values != nullptr) {
|
||||
option_values->~Multi_option_container();
|
||||
my_free(option_values);
|
||||
option_values = nullptr;
|
||||
}
|
||||
}
|
79
client/multi_option.h
Normal file
79
client/multi_option.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
Copyright (c) 2012, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mysql.h"
|
||||
#include "mysql/service_mysql_alloc.h"
|
||||
#include "prealloced_array.h"
|
||||
|
||||
#ifndef _MULTI_OPTION_H_
|
||||
#define _MULTI_OPTION_H_
|
||||
|
||||
/**
|
||||
Class for handling multiple options like e.g. --init-command,
|
||||
--init-command-add
|
||||
*/
|
||||
class Multi_option {
|
||||
/**
|
||||
Type of the internal container
|
||||
*/
|
||||
using Multi_option_container = Prealloced_array<char *, 5>;
|
||||
|
||||
public:
|
||||
/**
|
||||
Constaexpr constructor
|
||||
*/
|
||||
constexpr Multi_option() : option_values(nullptr) {}
|
||||
|
||||
/**
|
||||
Adds option value to the container
|
||||
|
||||
@param value [in]: value of the option
|
||||
@param clear [in]: if true the container will be cleared before adding the
|
||||
command
|
||||
*/
|
||||
void add_value(char *value, bool clear);
|
||||
|
||||
/**
|
||||
Sets options to MYSQL structure.
|
||||
|
||||
@param mysql [in, out]: pointer to MYSQL structure to be augmented with the
|
||||
option
|
||||
@param option [in]: option to be set
|
||||
*/
|
||||
void set_mysql_options(MYSQL *mysql, mysql_option option);
|
||||
|
||||
/**
|
||||
Free the commands
|
||||
*/
|
||||
void free();
|
||||
|
||||
private:
|
||||
/**
|
||||
The internal container with values
|
||||
*/
|
||||
Multi_option_container *option_values;
|
||||
};
|
||||
|
||||
#endif //_MULTI_OPTION_H_
|
54
client/my_readline.h
Normal file
54
client/my_readline.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
#ifndef CLIENT_MY_READLINE_INCLUDED
|
||||
#define CLIENT_MY_READLINE_INCLUDED
|
||||
|
||||
/*
|
||||
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* readline for batch mode */
|
||||
|
||||
#include "my_inttypes.h"
|
||||
#include "my_io.h"
|
||||
|
||||
struct LINE_BUFFER {
|
||||
File file;
|
||||
char *buffer; /* The buffer itself, grown as needed. */
|
||||
char *end; /* Pointer at buffer end */
|
||||
char *start_of_line, *end_of_line;
|
||||
uint bufread; /* Number of bytes to get with each read(). */
|
||||
uint eof;
|
||||
ulong max_size;
|
||||
ulong read_length; /* Length of last read string */
|
||||
int error;
|
||||
bool truncated;
|
||||
};
|
||||
|
||||
extern LINE_BUFFER *batch_readline_init(ulong max_size, FILE *file);
|
||||
extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char *str);
|
||||
extern char *batch_readline(LINE_BUFFER *buffer, bool binary_mode);
|
||||
extern void batch_readline_end(LINE_BUFFER *buffer);
|
||||
|
||||
static const unsigned long int batch_io_size = 16 * 1024 * 1024;
|
||||
|
||||
#endif /* CLIENT_MY_READLINE_INCLUDED */
|
5890
client/mysql.cc
Normal file
5890
client/mysql.cc
Normal file
File diff suppressed because it is too large
Load diff
1335
client/mysql_config_editor.cc
Normal file
1335
client/mysql_config_editor.cc
Normal file
File diff suppressed because it is too large
Load diff
875
client/mysql_secure_installation.cc
Normal file
875
client/mysql_secure_installation.cc
Normal file
|
@ -0,0 +1,875 @@
|
|||
/*
|
||||
Copyright (c) 2013, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "client/include/client_priv.h"
|
||||
#include "m_string.h"
|
||||
#ifdef _WIN32
|
||||
#include "mysql/strings/m_ctype.h"
|
||||
#endif
|
||||
#include "my_alloc.h"
|
||||
#include "my_compiler.h"
|
||||
#include "my_dbug.h"
|
||||
#include "my_default.h"
|
||||
#include "my_inttypes.h"
|
||||
#include "my_macros.h"
|
||||
#include "my_shm_defaults.h"
|
||||
#include "mysql/service_mysql_alloc.h"
|
||||
#include "mysqld_error.h"
|
||||
#include "nulls.h"
|
||||
#include "print_version.h"
|
||||
#include "typelib.h"
|
||||
#include "welcome_copyright_notice.h" // ORACLE_WELCOME_COPYRIGHT_NOTICE
|
||||
|
||||
using namespace std;
|
||||
|
||||
static MEM_ROOT argv_alloc{PSI_NOT_INSTRUMENTED, 512};
|
||||
static char *opt_host = nullptr;
|
||||
static char *opt_user = nullptr;
|
||||
static uint opt_port = 0;
|
||||
static uint opt_protocol = 0;
|
||||
static char *opt_socket = nullptr;
|
||||
static MYSQL mysql_handle;
|
||||
static char *password = nullptr;
|
||||
static bool password_provided = false;
|
||||
static bool g_expire_password_on_exit = false;
|
||||
static bool opt_use_default = false;
|
||||
|
||||
#if defined(_WIN32)
|
||||
static const char *shared_memory_base_name = default_shared_memory_base_name;
|
||||
#endif
|
||||
|
||||
#include "client/include/sslopt-vars.h"
|
||||
|
||||
static const char *load_default_groups[] = {"mysql_secure_installation",
|
||||
"mysql", "client", nullptr};
|
||||
|
||||
static struct my_option my_connection_options[] = {
|
||||
{"help", '?', "Display this help and exit.", nullptr, nullptr, nullptr,
|
||||
GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"host", 'h', "Connect to host.", &opt_host, &opt_host, nullptr,
|
||||
GET_STR_ALLOC, REQUIRED_ARG, (longlong) "localhost", 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"password", 'p',
|
||||
"Password to connect to the server. If password is not "
|
||||
"given it's asked from the tty.",
|
||||
nullptr, nullptr, nullptr, GET_PASSWORD, OPT_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
#ifdef _WIN32
|
||||
{"pipe", 'W', "Use named pipes to connect to server.", nullptr, nullptr,
|
||||
nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#endif
|
||||
{"port", 'P',
|
||||
"Port number to use for connection or 0 for default to, in "
|
||||
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
|
||||
#if MYSQL_PORT_DEFAULT == 0
|
||||
"/etc/services, "
|
||||
#endif
|
||||
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
|
||||
&opt_port, &opt_port, nullptr, GET_UINT, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"protocol", OPT_MYSQL_PROTOCOL,
|
||||
"The protocol to use for connection (tcp, socket, pipe, memory).", nullptr,
|
||||
nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#if defined(_WIN32)
|
||||
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
|
||||
"Base name of shared memory.", &shared_memory_base_name,
|
||||
&shared_memory_base_name, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
#endif
|
||||
{"socket", 'S', "Socket file to be used for connection.", &opt_socket,
|
||||
&opt_socket, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
#include "client/include/sslopt-longopts.h"
|
||||
|
||||
{"user", 'u', "User for login if not root.", &opt_user, &opt_user, nullptr,
|
||||
GET_STR_ALLOC, REQUIRED_ARG, (longlong) "root", 0, 0, nullptr, 0, nullptr},
|
||||
{"use-default", 'D', "Execute with no user interactivity", &opt_use_default,
|
||||
&opt_use_default, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
/* End token */
|
||||
{nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
|
||||
0, nullptr, 0, nullptr}};
|
||||
|
||||
static void usage() {
|
||||
print_version();
|
||||
fprintf(stdout, ORACLE_WELCOME_COPYRIGHT_NOTICE("2013"));
|
||||
fprintf(stdout, "\nMySQL Configuration Utility.");
|
||||
fprintf(stdout, "Usage: %s [OPTIONS]\n", my_progname);
|
||||
my_print_help(my_connection_options);
|
||||
print_defaults("my", load_default_groups);
|
||||
my_print_variables(my_connection_options);
|
||||
}
|
||||
|
||||
static void free_resources() {
|
||||
if (opt_host) my_free(opt_host);
|
||||
if (opt_socket) my_free(opt_socket);
|
||||
if (opt_user) my_free(opt_user);
|
||||
if (password) my_free(password);
|
||||
mysql_close(&mysql_handle);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static bool my_arguments_get_one_option(int optid,
|
||||
const struct my_option *opt
|
||||
[[maybe_unused]],
|
||||
char *argument) {
|
||||
switch (optid) {
|
||||
case '?':
|
||||
usage();
|
||||
free_resources();
|
||||
exit(0);
|
||||
case 'p':
|
||||
if (argument) {
|
||||
char *start = argument;
|
||||
my_free(password);
|
||||
password = my_strdup(PSI_NOT_INSTRUMENTED, argument, MYF(MY_FAE));
|
||||
while (*argument) {
|
||||
*argument++ = 'x'; // Destroy argument
|
||||
}
|
||||
if (*start) start[1] = 0;
|
||||
} else
|
||||
password = get_tty_password(NullS);
|
||||
password_provided = true;
|
||||
break;
|
||||
|
||||
#include "client/include/sslopt-case.h"
|
||||
|
||||
case OPT_MYSQL_PROTOCOL:
|
||||
opt_protocol =
|
||||
find_type_or_exit(argument, &sql_protocol_typelib, opt->name);
|
||||
break;
|
||||
case 'W':
|
||||
#ifdef _WIN32
|
||||
opt_protocol = MYSQL_PROTOCOL_PIPE;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize options for the given connection handle. */
|
||||
static void init_connection_options(MYSQL *mysql) {
|
||||
SSL_SET_OPTIONS(mysql);
|
||||
|
||||
if (opt_protocol)
|
||||
mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char *)&opt_protocol);
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (shared_memory_base_name)
|
||||
mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
|
||||
shared_memory_base_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Reads the response from stdin and returns the first character.
|
||||
If global variable opt_use_default is true then the default_answer is
|
||||
returned instead.
|
||||
@param opt_message Optional message do be displayed.
|
||||
@param default_answer Answer to be given if no interactivity is allowed.
|
||||
@return First character of input string
|
||||
*/
|
||||
|
||||
static int get_response(const char *opt_message, int default_answer = -1) {
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
int i = 0;
|
||||
if (opt_message) {
|
||||
fprintf(stdout, "%s", opt_message);
|
||||
if (opt_use_default == true && default_answer != -1) {
|
||||
fprintf(stdout, " %c \n", (char)default_answer);
|
||||
return default_answer;
|
||||
}
|
||||
}
|
||||
do {
|
||||
if (i == 1) b = a;
|
||||
a = getchar();
|
||||
i++;
|
||||
} while (a != '\n');
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
Takes a mysql query and an optional message as arguments.
|
||||
It displays the message if provided one and then runs the query.
|
||||
If the query is run successfully, the success message is displayed.
|
||||
Else, the failure message along with the actual failure is displayed.
|
||||
If the server is not found running, the program is exited.
|
||||
|
||||
@param query The mysql query which is to be executed.
|
||||
@param opt_message The optional message to be displayed.
|
||||
*/
|
||||
static void execute_query_with_message(const char *query,
|
||||
const char *opt_message) {
|
||||
if (opt_message) fprintf(stdout, "%s", opt_message);
|
||||
|
||||
if (!mysql_query(&mysql_handle, query))
|
||||
fprintf(stdout, "Success.\n\n");
|
||||
else if ((mysql_errno(&mysql_handle) == ER_PROCACCESS_DENIED_ERROR) ||
|
||||
(mysql_errno(&mysql_handle) == ER_TABLEACCESS_DENIED_ERROR) ||
|
||||
(mysql_errno(&mysql_handle) == ER_COLUMNACCESS_DENIED_ERROR)) {
|
||||
fprintf(stdout,
|
||||
"The user provided does not have enough permissions "
|
||||
"to continue.\nmysql_secure_installation is exiting.\n");
|
||||
free_resources();
|
||||
exit(1);
|
||||
} else
|
||||
fprintf(stdout, " ... Failed! Error: %s\n", mysql_error(&mysql_handle));
|
||||
|
||||
if (mysql_errno(&mysql_handle) == CR_SERVER_GONE_ERROR) {
|
||||
free_resources();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Takes a mysql query and the length of the query in bytes
|
||||
as the input. If the query fails on running, a message
|
||||
along with the failure details is displayed.
|
||||
|
||||
@param query The mysql query which is to be executed.
|
||||
@param length Length of the query in bytes.
|
||||
|
||||
@return false in case of success
|
||||
true in case of failure
|
||||
*/
|
||||
static bool execute_query(const char **query, size_t length) {
|
||||
if (!mysql_real_query(&mysql_handle, (const char *)*query, (ulong)length))
|
||||
return false;
|
||||
else if (mysql_errno(&mysql_handle) == CR_SERVER_GONE_ERROR) {
|
||||
fprintf(stdout, " ... Failed! Error: %s\n", mysql_error(&mysql_handle));
|
||||
free_resources();
|
||||
exit(1);
|
||||
}
|
||||
if ((mysql_errno(&mysql_handle) == ER_PROCACCESS_DENIED_ERROR) ||
|
||||
(mysql_errno(&mysql_handle) == ER_TABLEACCESS_DENIED_ERROR) ||
|
||||
(mysql_errno(&mysql_handle) == ER_COLUMNACCESS_DENIED_ERROR)) {
|
||||
fprintf(stdout,
|
||||
"The user provided does not have enough permissions "
|
||||
"to continue.\nmysql_secure_installation is exiting.\n");
|
||||
free_resources();
|
||||
exit(1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if the validate_password component is installed and returns true
|
||||
if it is.
|
||||
*/
|
||||
static bool validate_password_exists() {
|
||||
MYSQL_ROW row;
|
||||
bool res = true;
|
||||
const char *query =
|
||||
"SELECT component_urn FROM mysql.component WHERE component_urn "
|
||||
"= \'file://component_validate_password\'";
|
||||
if (!execute_query(&query, strlen(query)))
|
||||
DBUG_PRINT("info", ("query success!"));
|
||||
MYSQL_RES *result = mysql_store_result(&mysql_handle);
|
||||
if (!result) return false;
|
||||
row = mysql_fetch_row(result);
|
||||
if (!row) res = false;
|
||||
|
||||
mysql_free_result(result);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
Installs validate_password component and sets the password validation policy.
|
||||
|
||||
@return Returns 1 on successfully setting the component and 0 in case of
|
||||
of any error.
|
||||
*/
|
||||
static int install_password_validation_component() {
|
||||
int reply;
|
||||
int component_set = 0;
|
||||
const char *strength = nullptr;
|
||||
bool option_read = false;
|
||||
reply= get_response((const char *) "\nVALIDATE PASSWORD COMPONENT can be "
|
||||
"used to test passwords\nand improve "
|
||||
"security. It checks the strength of "
|
||||
"password\nand allows the users to set "
|
||||
"only those passwords which are\nsecure "
|
||||
"enough. Would you like to setup VALIDATE "
|
||||
"PASSWORD component?\n\nPress y|Y for Yes,"
|
||||
" any other key for No: ", 'y');
|
||||
if (reply == (int)'y' || reply == (int)'Y') {
|
||||
const char *query_tmp;
|
||||
query_tmp = "INSTALL COMPONENT 'file://component_validate_password'";
|
||||
if (!execute_query(&query_tmp, strlen(query_tmp))) {
|
||||
component_set = 1;
|
||||
while (!option_read) {
|
||||
reply= get_response((const char *) "\nThere are three levels of "
|
||||
"password validation policy:\n\n"
|
||||
"LOW Length >= 8\n"
|
||||
"MEDIUM Length >= 8, numeric, mixed case, and special characters\n"
|
||||
"STRONG Length >= 8, numeric, mixed case, special characters and dictionary"
|
||||
" file\n\n"
|
||||
"Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: ",'2');
|
||||
switch (reply) {
|
||||
case (int)'0':
|
||||
strength = "LOW";
|
||||
option_read = true;
|
||||
break;
|
||||
case (int)'1':
|
||||
strength = "MEDIUM";
|
||||
option_read = true;
|
||||
break;
|
||||
case (int)'2':
|
||||
strength = "STRONG";
|
||||
option_read = true;
|
||||
break;
|
||||
default:
|
||||
fprintf(stdout, "\nInvalid option provided.\n");
|
||||
}
|
||||
}
|
||||
char *query, *end;
|
||||
const int tmp = sizeof("SET GLOBAL validate_password.policy = ") + 3;
|
||||
const size_t strength_length = strlen(strength);
|
||||
/*
|
||||
query string needs memory which is at least the length of initial part
|
||||
of query plus twice the size of variable being appended.
|
||||
*/
|
||||
query = (char *)my_malloc(PSI_NOT_INSTRUMENTED,
|
||||
(strength_length * 2 + tmp) * sizeof(char),
|
||||
MYF(MY_WME));
|
||||
end = my_stpcpy(query, "SET GLOBAL validate_password.policy = ");
|
||||
*end++ = '\'';
|
||||
end += mysql_real_escape_string_quote(&mysql_handle, end, strength,
|
||||
(ulong)strength_length, '\'');
|
||||
*end++ = '\'';
|
||||
const char *query_const = query;
|
||||
if (!execute_query(&query_const, (unsigned int)(end - query)))
|
||||
DBUG_PRINT("info", ("query success!"));
|
||||
my_free(query);
|
||||
} else
|
||||
fprintf(stdout,
|
||||
"The password validation component is not available. "
|
||||
"Proceeding with the further steps without the component.\n");
|
||||
}
|
||||
return (component_set);
|
||||
}
|
||||
|
||||
/**
|
||||
Checks the password strength and displays it to the user.
|
||||
|
||||
@param password_string Password string whose strength
|
||||
is to be estimated
|
||||
*/
|
||||
static void estimate_password_strength(char *password_string) {
|
||||
char *query, *end;
|
||||
const size_t tmp = sizeof("SELECT validate_password_strength(") + 3;
|
||||
const size_t password_length = strlen(password_string);
|
||||
/*
|
||||
query string needs memory which is at least the length of initial part
|
||||
of query plus twice the size of variable being appended.
|
||||
*/
|
||||
query = (char *)my_malloc(PSI_NOT_INSTRUMENTED,
|
||||
(password_length * 2 + tmp) * sizeof(char),
|
||||
MYF(MY_WME));
|
||||
end = my_stpcpy(query, "SELECT validate_password_strength(");
|
||||
*end++ = '\'';
|
||||
end += mysql_real_escape_string_quote(&mysql_handle, end, password_string,
|
||||
(ulong)password_length, '\'');
|
||||
*end++ = '\'';
|
||||
*end++ = ')';
|
||||
const char *query_const = query;
|
||||
if (!execute_query(&query_const, (unsigned int)(end - query))) {
|
||||
MYSQL_RES *result = mysql_store_result(&mysql_handle);
|
||||
MYSQL_ROW row = mysql_fetch_row(result);
|
||||
printf("\nEstimated strength of the password: %s \n", row[0]);
|
||||
mysql_free_result(result);
|
||||
}
|
||||
my_free(query);
|
||||
}
|
||||
|
||||
/**
|
||||
During rpm deployments the password expires immediately and needs to be
|
||||
renewed before the DBA can set the final password. This helper subroutine
|
||||
will use an active connection to set a password.
|
||||
|
||||
@param mysql The MYSQL handle
|
||||
@param password A password character string
|
||||
|
||||
Function might fail with an error message which can be retrieved using
|
||||
mysql_error(mysql)
|
||||
|
||||
@return Success or failure
|
||||
@retval true success
|
||||
@retval false failure
|
||||
*/
|
||||
|
||||
static bool mysql_set_password(MYSQL *mysql, char *password) {
|
||||
const size_t password_len = strlen(password);
|
||||
char *query, *end;
|
||||
query =
|
||||
(char *)my_malloc(PSI_NOT_INSTRUMENTED, password_len + 50, MYF(MY_WME));
|
||||
end = my_stpmov(query, "SET PASSWORD=");
|
||||
*end++ = '\'';
|
||||
end += mysql_real_escape_string_quote(mysql, end, password,
|
||||
(ulong)password_len, '\'');
|
||||
*end++ = '\'';
|
||||
if (mysql_real_query(mysql, query, (ulong)(end - query))) {
|
||||
my_free(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
my_free(query);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Expires the password for all users if executed with sufficient
|
||||
privileges. This is primarily used as a helper function during rpm
|
||||
deployments.
|
||||
|
||||
@param mysql The MYSQL handle
|
||||
|
||||
Function might fail with an error message which can be retrieved using
|
||||
mysql_error(mysql)
|
||||
|
||||
@return Success or failure
|
||||
@retval true success
|
||||
@retval false failure
|
||||
*/
|
||||
|
||||
static bool mysql_expire_password(MYSQL *mysql) {
|
||||
char sql[] = "UPDATE mysql.user SET password_expired= 'Y'";
|
||||
const size_t sql_len = strlen(sql);
|
||||
if (mysql_real_query(mysql, sql, (ulong)sql_len)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the user password with the string provided during the flow
|
||||
of the method. It checks for the strength of the password before
|
||||
changing it and displays the same to the user. The user can decide
|
||||
if he wants to continue with the password, or provide a new one,
|
||||
depending on the strength displayed.
|
||||
|
||||
@param component_set 1 if validate_password component is set and
|
||||
0 if it is not.
|
||||
*/
|
||||
|
||||
static void set_opt_user_password(int component_set) {
|
||||
char *password1 = nullptr, *password2 = nullptr;
|
||||
int reply = 0;
|
||||
|
||||
for (;;) {
|
||||
if (password1) {
|
||||
my_free(password1);
|
||||
password1 = nullptr;
|
||||
}
|
||||
if (password2) {
|
||||
my_free(password2);
|
||||
password2 = nullptr;
|
||||
}
|
||||
|
||||
password1 = get_tty_password("\nNew password: ");
|
||||
|
||||
if (password1[0] == '\0') {
|
||||
fprintf(stdout, "Sorry, you can't use an empty password here.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
password2 = get_tty_password("\nRe-enter new password: ");
|
||||
|
||||
if (strcmp(password1, password2)) {
|
||||
fprintf(stdout, "Sorry, passwords do not match.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (component_set == 1) {
|
||||
estimate_password_strength(password1);
|
||||
reply = get_response((
|
||||
const char *)"Do you wish to continue with the "
|
||||
"password provided?(Press y|Y for "
|
||||
"Yes, any other key for No) : ");
|
||||
}
|
||||
|
||||
const size_t pass_length = strlen(password1);
|
||||
|
||||
if ((!component_set) || (reply == (int)'y' || reply == (int)'Y')) {
|
||||
char *query = nullptr, *end;
|
||||
const int tmp = sizeof("SET PASSWORD=") + 3;
|
||||
/*
|
||||
query string needs memory which is at least the length of initial part
|
||||
of query plus twice the size of variable being appended.
|
||||
*/
|
||||
query = (char *)my_malloc(PSI_NOT_INSTRUMENTED,
|
||||
(pass_length * 2 + tmp) * sizeof(char),
|
||||
MYF(MY_WME));
|
||||
end = my_stpcpy(query, "SET PASSWORD=");
|
||||
*end++ = '\'';
|
||||
end += mysql_real_escape_string_quote(&mysql_handle, end, password1,
|
||||
(ulong)pass_length, '\'');
|
||||
*end++ = '\'';
|
||||
my_free(password1);
|
||||
my_free(password2);
|
||||
password1 = nullptr;
|
||||
password2 = nullptr;
|
||||
const char *query_const = query;
|
||||
if (!execute_query(&query_const, (unsigned int)(end - query))) {
|
||||
my_free(query);
|
||||
break;
|
||||
} else
|
||||
fprintf(stdout, " ... Failed! Error: %s\n", mysql_error(&mysql_handle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Takes the opt_user's password as an input from the user and checks its
|
||||
validity by trying to connect to the server with it. The connection to the
|
||||
server is opened in this function.
|
||||
|
||||
@return Returns 1 if a password already exists and 0 if it doesn't.
|
||||
*/
|
||||
static int get_opt_user_password() {
|
||||
bool using_temporary_password = false;
|
||||
int res;
|
||||
|
||||
if (!password_provided) {
|
||||
/*
|
||||
No password is provided on the command line. Attempt to connect using
|
||||
a blank password.
|
||||
*/
|
||||
MYSQL *con = mysql_real_connect(&mysql_handle, opt_host, opt_user, "", "",
|
||||
opt_port, opt_socket, 0);
|
||||
if (con != nullptr ||
|
||||
mysql_errno(&mysql_handle) == ER_MUST_CHANGE_PASSWORD_LOGIN) {
|
||||
fprintf(stdout, "Connecting to MySQL using a blank password.\n");
|
||||
my_free(password);
|
||||
password = nullptr;
|
||||
mysql_close(con);
|
||||
} else {
|
||||
char prompt[128];
|
||||
snprintf(prompt, sizeof(prompt) - 1,
|
||||
"Enter password for user %s: ", opt_user);
|
||||
// Request password from user
|
||||
password = get_tty_password(prompt);
|
||||
}
|
||||
init_connection_options(&mysql_handle);
|
||||
} // if !password_provided
|
||||
|
||||
/*
|
||||
A password candidate is identified. Use it to establish a connection.
|
||||
*/
|
||||
if (!mysql_real_connect(&mysql_handle, opt_host, opt_user, password, "",
|
||||
opt_port, opt_socket, 0)) {
|
||||
if (mysql_errno(&mysql_handle) == ER_MUST_CHANGE_PASSWORD_LOGIN) {
|
||||
bool can = true;
|
||||
init_connection_options(&mysql_handle);
|
||||
mysql_options(&mysql_handle, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
|
||||
&can);
|
||||
if (!mysql_real_connect(&mysql_handle, opt_host, opt_user, password, "",
|
||||
opt_port, opt_socket, 0)) {
|
||||
fprintf(stdout, "Error: %s\n", mysql_error(&mysql_handle));
|
||||
free_resources();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
Password worked but has expired. If this happens during a silent
|
||||
deployment using the rpm package system we cannot stop and ask
|
||||
for a password. Instead we just renew the previous password and set
|
||||
it to expire.
|
||||
*/
|
||||
if (using_temporary_password) {
|
||||
if (!mysql_set_password(&mysql_handle, password)) {
|
||||
fprintf(stdout, "... Failed! Error: %s\n",
|
||||
mysql_error(&mysql_handle));
|
||||
free_resources();
|
||||
exit(1);
|
||||
}
|
||||
g_expire_password_on_exit = true;
|
||||
} else {
|
||||
/*
|
||||
This path is only executed if no temporary password can be found and
|
||||
should only happen when manual interaction is possible.
|
||||
*/
|
||||
fprintf(stdout,
|
||||
"\nThe existing password for the user account %s has "
|
||||
"expired. Please set a new password.\n",
|
||||
opt_user);
|
||||
set_opt_user_password(0);
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout, "Error: %s\n", mysql_error(&mysql_handle));
|
||||
free_resources();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
res = (password && password[0] != '\0') ? 1 : 0;
|
||||
return (res);
|
||||
}
|
||||
|
||||
/**
|
||||
Takes the user and the host from result set and drops those users.
|
||||
|
||||
@param result The result set from which rows are to be fetched.
|
||||
*/
|
||||
static void drop_users(MYSQL_RES *result) {
|
||||
MYSQL_ROW row;
|
||||
char *user_tmp, *host_tmp;
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
char *query, *end;
|
||||
size_t user_length, host_length;
|
||||
const int tmp = sizeof("DROP USER ") + 5;
|
||||
user_tmp = row[0];
|
||||
host_tmp = row[1];
|
||||
user_length = strlen(user_tmp);
|
||||
host_length = strlen(host_tmp);
|
||||
/*
|
||||
query string needs memory which is at least the length of initial part
|
||||
of query plus twice the size of variable being appended.
|
||||
*/
|
||||
query = (char *)my_malloc(
|
||||
PSI_NOT_INSTRUMENTED,
|
||||
((user_length + host_length) * 2 + tmp) * sizeof(char), MYF(MY_WME));
|
||||
end = my_stpcpy(query, "DROP USER ");
|
||||
*end++ = '\'';
|
||||
end += mysql_real_escape_string_quote(&mysql_handle, end, user_tmp,
|
||||
(ulong)user_length, '\'');
|
||||
*end++ = '\'';
|
||||
*end++ = '@';
|
||||
*end++ = '\'';
|
||||
end += mysql_real_escape_string_quote(&mysql_handle, end, host_tmp,
|
||||
(ulong)host_length, '\'');
|
||||
*end++ = '\'';
|
||||
const char *query_const = query;
|
||||
if (!execute_query(&query_const, (unsigned int)(end - query)))
|
||||
DBUG_PRINT("info", ("query success!"));
|
||||
my_free(query);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Removes all the anonymous users for better security.
|
||||
*/
|
||||
static void remove_anonymous_users() {
|
||||
int reply;
|
||||
reply= get_response((const char *) "By default, a MySQL installation has an "
|
||||
"anonymous user,\nallowing anyone to log "
|
||||
"into MySQL without having to have\na user "
|
||||
"account created for them. This is intended "
|
||||
"only for\ntesting, and to make the "
|
||||
"installation go a bit smoother.\nYou should "
|
||||
"remove them before moving into a production\n"
|
||||
"environment.\n\nRemove anonymous users? "
|
||||
"(Press y|Y for Yes, any other key for No) : ", 'y');
|
||||
|
||||
if (reply == (int)'y' || reply == (int)'Y') {
|
||||
const char *query;
|
||||
query = "SELECT USER, HOST FROM mysql.user WHERE USER=''";
|
||||
if (!execute_query(&query, strlen(query)))
|
||||
DBUG_PRINT("info", ("query success!"));
|
||||
MYSQL_RES *result = mysql_store_result(&mysql_handle);
|
||||
if (result) drop_users(result);
|
||||
mysql_free_result(result);
|
||||
fprintf(stdout, "Success.\n\n");
|
||||
} else
|
||||
fprintf(stdout, "\n ... skipping.\n\n");
|
||||
}
|
||||
|
||||
/**
|
||||
Drops all the root users with a remote host.
|
||||
*/
|
||||
static void remove_remote_root() {
|
||||
int reply;
|
||||
reply= get_response((const char *) "\nNormally, root should only be "
|
||||
"allowed to connect from\n'localhost'. "
|
||||
"This ensures that someone cannot guess at"
|
||||
"\nthe root password from the network.\n\n"
|
||||
"Disallow root login remotely? (Press y|Y "
|
||||
"for Yes, any other key for No) : ", 'y');
|
||||
if (reply == (int)'y' || reply == (int)'Y') {
|
||||
const char *query;
|
||||
query =
|
||||
"SELECT USER, HOST FROM mysql.user WHERE USER='root' "
|
||||
"AND HOST NOT IN ('localhost', '127.0.0.1', '::1')";
|
||||
if (!execute_query(&query, strlen(query)))
|
||||
DBUG_PRINT("info", ("query success!"));
|
||||
MYSQL_RES *result = mysql_store_result(&mysql_handle);
|
||||
if (result) drop_users(result);
|
||||
mysql_free_result(result);
|
||||
fprintf(stdout, "Success.\n\n");
|
||||
} else
|
||||
fprintf(stdout, "\n ... skipping.\n");
|
||||
}
|
||||
|
||||
/**
|
||||
Removes test database and deletes the rows corresponding to them
|
||||
from mysql.db table.
|
||||
*/
|
||||
static void remove_test_database() {
|
||||
int reply;
|
||||
reply= get_response((const char *) "By default, MySQL comes with a database "
|
||||
"named 'test' that\nanyone can access. "
|
||||
"This is also intended only for testing,\n"
|
||||
"and should be removed before moving into "
|
||||
"a production\nenvironment.\n\n\nRemove "
|
||||
"test database and access to it? (Press "
|
||||
"y|Y for Yes, any other key for No) : ", 'y');
|
||||
if (reply == (int)'y' || reply == (int)'Y') {
|
||||
execute_query_with_message((const char *)"DROP DATABASE IF EXISTS test",
|
||||
(const char *)" - Dropping test database...\n");
|
||||
|
||||
execute_query_with_message((const char *) "DELETE FROM mysql.db WHERE "
|
||||
"Db='test' OR Db='test\\_%'",
|
||||
(const char *) " - Removing privileges on test "
|
||||
"database...\n");
|
||||
} else
|
||||
fprintf(stdout, "\n ... skipping.\n");
|
||||
}
|
||||
|
||||
/**
|
||||
Refreshes the in-memory details through
|
||||
FLUSH PRIVILEGES.
|
||||
*/
|
||||
static void reload_privilege_tables() {
|
||||
int reply;
|
||||
reply= get_response((const char *) "Reloading the privilege tables will "
|
||||
"ensure that all changes\nmade so far "
|
||||
"will take effect immediately.\n\nReload "
|
||||
"privilege tables now? (Press y|Y for "
|
||||
"Yes, any other key for No) : ", 'y');
|
||||
if (reply == (int)'y' || reply == (int)'Y') {
|
||||
execute_query_with_message((const char *)"FLUSH PRIVILEGES", nullptr);
|
||||
} else
|
||||
fprintf(stdout, "\n ... skipping.\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int reply;
|
||||
int rc;
|
||||
int hadpass, component_set = 0;
|
||||
|
||||
MY_INIT(argv[0]);
|
||||
DBUG_TRACE;
|
||||
DBUG_PROCESS(argv[0]);
|
||||
if (mysql_init(&mysql_handle) == nullptr) {
|
||||
printf("... Failed to initialize the MySQL client framework.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Convert command line parameters from UTF16LE to UTF8MB4. */
|
||||
my_win_translate_command_line_args(&my_charset_utf8mb4_bin, &argc, &argv);
|
||||
#endif
|
||||
|
||||
my_getopt_use_args_separator = true;
|
||||
if (load_defaults("my", load_default_groups, &argc, &argv, &argv_alloc)) {
|
||||
my_end(0);
|
||||
free_resources();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
my_getopt_use_args_separator = false;
|
||||
|
||||
if ((rc = my_handle_options(&argc, &argv, my_connection_options,
|
||||
my_arguments_get_one_option, nullptr, true))) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
init_connection_options(&mysql_handle);
|
||||
|
||||
fprintf(stdout, "\nSecuring the MySQL server deployment.\n\n");
|
||||
|
||||
hadpass = get_opt_user_password();
|
||||
|
||||
if (!validate_password_exists())
|
||||
component_set = install_password_validation_component();
|
||||
else {
|
||||
fprintf(stdout,
|
||||
"The 'validate_password' component is installed on the server.\n"
|
||||
"The subsequent steps will run with the existing "
|
||||
"configuration\nof the component.\n");
|
||||
component_set = 1;
|
||||
}
|
||||
|
||||
if (!hadpass) {
|
||||
fprintf(stdout, "Please set the password for %s here.\n", opt_user);
|
||||
set_opt_user_password(component_set);
|
||||
} else if (opt_use_default == false) {
|
||||
char prompt[256];
|
||||
fprintf(stdout, "Using existing password for %s.\n", opt_user);
|
||||
|
||||
if (component_set == 1) estimate_password_strength(password);
|
||||
|
||||
snprintf(prompt, sizeof(prompt) - 1,
|
||||
"Change the password for %s ? ((Press y|Y "
|
||||
"for Yes, any other key for No) : ",
|
||||
opt_user);
|
||||
reply = get_response(prompt, 'n');
|
||||
|
||||
if (reply == (int)'y' || reply == (int)'Y')
|
||||
set_opt_user_password(component_set);
|
||||
else
|
||||
fprintf(stdout, "\n ... skipping.\n");
|
||||
}
|
||||
|
||||
// Remove anonymous users
|
||||
remove_anonymous_users();
|
||||
|
||||
// Disallow remote root login
|
||||
remove_remote_root();
|
||||
|
||||
// Remove test database
|
||||
remove_test_database();
|
||||
|
||||
/*
|
||||
During an unattended rpm deployment a temporary password is created and
|
||||
stored in a file by 'mysqld --initialize'. This program uses this password
|
||||
to perform security configurations after the bootstrap phase, but it needs
|
||||
to be marked for expiration upon exit so the DBA will remember to set a new
|
||||
one.
|
||||
*/
|
||||
if (g_expire_password_on_exit == true) {
|
||||
if (mysql_expire_password(&mysql_handle) == false) {
|
||||
fprintf(stdout,
|
||||
"... Failed to expire password!\n"
|
||||
"** Please consult the MySQL server documentation. **\n"
|
||||
"Error: %s\n",
|
||||
mysql_error(&mysql_handle));
|
||||
// Reload privilege tables before exiting
|
||||
reload_privilege_tables();
|
||||
free_resources();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Reload privilege tables
|
||||
reload_privilege_tables();
|
||||
|
||||
fprintf(stdout, "All done! \n");
|
||||
free_resources();
|
||||
return 0;
|
||||
}
|
1541
client/mysqladmin.cc
Normal file
1541
client/mysqladmin.cc
Normal file
File diff suppressed because it is too large
Load diff
3534
client/mysqlbinlog.cc
Normal file
3534
client/mysqlbinlog.cc
Normal file
File diff suppressed because it is too large
Load diff
49
client/mysqlbinlog.h
Normal file
49
client/mysqlbinlog.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* Copyright (c) 2015, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef MYSQLBINLOG_INCLUDED
|
||||
#define MYSQLBINLOG_INCLUDED
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "my_compiler.h"
|
||||
#include "my_inttypes.h"
|
||||
|
||||
extern bool force_opt;
|
||||
extern bool short_form;
|
||||
extern ulong opt_server_id_mask;
|
||||
extern ulong opt_binlog_rows_event_max_size;
|
||||
|
||||
/*
|
||||
error() is used in macro BINLOG_ERROR which is invoked in
|
||||
rpl_gtid.h, hence the early forward declaration.
|
||||
*/
|
||||
void error(const char *format, ...) MY_ATTRIBUTE((format(printf, 1, 2)));
|
||||
void warning(const char *format, ...) MY_ATTRIBUTE((format(printf, 1, 2)));
|
||||
void error_or_warning(const char *format, va_list args, const char *msg)
|
||||
MY_ATTRIBUTE((format(printf, 1, 0)));
|
||||
void sql_print_error(const char *format, ...)
|
||||
MY_ATTRIBUTE((format(printf, 1, 2)));
|
||||
|
||||
#endif // MYSQLBINLOG_INCLUDED
|
6466
client/mysqldump.cc
Normal file
6466
client/mysqldump.cc
Normal file
File diff suppressed because it is too large
Load diff
723
client/mysqlimport.cc
Normal file
723
client/mysqlimport.cc
Normal file
|
@ -0,0 +1,723 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
** mysqlimport.c - Imports all given files
|
||||
** into a table(s).
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "client/include/client_priv.h"
|
||||
#include "compression.h"
|
||||
#include "m_string.h"
|
||||
#include "my_alloc.h"
|
||||
#include "my_dbug.h"
|
||||
#include "my_default.h"
|
||||
#include "my_inttypes.h"
|
||||
#include "my_io.h"
|
||||
#include "my_macros.h"
|
||||
#include "my_systime.h"
|
||||
#include "mysql/service_mysql_alloc.h"
|
||||
#include "mysql/strings/int2str.h"
|
||||
#include "mysql_version.h"
|
||||
#include "nulls.h"
|
||||
#include "print_version.h"
|
||||
#include "strxmov.h"
|
||||
#include "thr_cond.h"
|
||||
#include "thr_mutex.h"
|
||||
#include "typelib.h"
|
||||
#include "welcome_copyright_notice.h" /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
|
||||
|
||||
/* Global Thread counter */
|
||||
uint counter;
|
||||
native_mutex_t init_mutex;
|
||||
native_mutex_t counter_mutex;
|
||||
native_cond_t count_threshold;
|
||||
|
||||
static int db_error_with_table(MYSQL *mysql, char *table);
|
||||
static int db_error(MYSQL *mysql);
|
||||
static char *field_escape(char *to, const char *from, uint length);
|
||||
static char *add_load_option(char *ptr, const char *object,
|
||||
const char *statement);
|
||||
|
||||
static bool verbose = false, lock_tables = false, ignore_errors = false,
|
||||
opt_delete = false, replace = false, silent = false, ignore = false,
|
||||
opt_compress = false, opt_low_priority = false;
|
||||
static bool debug_info_flag = false, debug_check_flag = false;
|
||||
static uint opt_use_threads = 0, opt_local_file = 0, my_end_arg = 0;
|
||||
static char *current_user = nullptr, *current_host = nullptr,
|
||||
*current_db = nullptr, *fields_terminated = nullptr,
|
||||
*lines_terminated = nullptr, *enclosed = nullptr,
|
||||
*opt_enclosed = nullptr, *escaped = nullptr, *opt_columns = nullptr;
|
||||
static const char *default_charset = MYSQL_AUTODETECT_CHARSET_NAME;
|
||||
static uint opt_enable_cleartext_plugin = 0;
|
||||
static bool using_opt_enable_cleartext_plugin = false;
|
||||
static uint opt_mysql_port = 0, opt_protocol = 0;
|
||||
static char *opt_bind_addr = nullptr;
|
||||
static char *opt_mysql_unix_port = nullptr;
|
||||
static char *opt_plugin_dir = nullptr, *opt_default_auth = nullptr;
|
||||
static longlong opt_ignore_lines = -1;
|
||||
static uint opt_zstd_compress_level = default_zstd_compression_level;
|
||||
static char *opt_compress_algorithm = nullptr;
|
||||
|
||||
#include "client/include/caching_sha2_passwordopt-vars.h"
|
||||
#include "client/include/multi_factor_passwordopt-vars.h"
|
||||
#include "client/include/sslopt-vars.h"
|
||||
#if defined(_WIN32)
|
||||
static char *shared_memory_base_name = nullptr;
|
||||
#endif
|
||||
|
||||
static struct my_option my_long_options[] = {
|
||||
{"bind-address", 0, "IP address to bind to.", (uchar **)&opt_bind_addr,
|
||||
(uchar **)&opt_bind_addr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr,
|
||||
0, nullptr},
|
||||
{"character-sets-dir", OPT_CHARSETS_DIR,
|
||||
"Directory for character set files.", &charsets_dir, &charsets_dir,
|
||||
nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"default-character-set", OPT_DEFAULT_CHARSET,
|
||||
"Set the default character set.", &default_charset, &default_charset,
|
||||
nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"columns", 'c',
|
||||
"Use only these columns to import the data to. Give the column names in a "
|
||||
"comma separated list. This is same as giving columns to LOAD DATA "
|
||||
"INFILE.",
|
||||
&opt_columns, &opt_columns, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"compress", 'C', "Use compression in server/client protocol.",
|
||||
&opt_compress, &opt_compress, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr,
|
||||
0, nullptr},
|
||||
#ifdef NDEBUG
|
||||
{"debug", '#', "This is a non-debug version. Catch this and exit.", nullptr,
|
||||
nullptr, nullptr, GET_DISABLED, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"debug-check", OPT_DEBUG_CHECK,
|
||||
"This is a non-debug version. Catch this and exit.", nullptr, nullptr,
|
||||
nullptr, GET_DISABLED, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"debug-info", OPT_DEBUG_INFO,
|
||||
"This is a non-debug version. Catch this and exit.", nullptr, nullptr,
|
||||
nullptr, GET_DISABLED, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#else
|
||||
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", nullptr,
|
||||
nullptr, nullptr, GET_STR, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"debug-check", OPT_DEBUG_CHECK,
|
||||
"Check memory and open file usage at exit.", &debug_check_flag,
|
||||
&debug_check_flag, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
|
||||
&debug_info_flag, &debug_info_flag, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
#endif
|
||||
{"default_auth", OPT_DEFAULT_AUTH,
|
||||
"Default authentication client-side plugin to use.", &opt_default_auth,
|
||||
&opt_default_auth, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"delete", 'd', "First delete all rows from table.", &opt_delete,
|
||||
&opt_delete, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
|
||||
"Enable/disable the clear text authentication plugin.",
|
||||
&opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin, nullptr,
|
||||
GET_BOOL, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"fields-terminated-by", OPT_FTB,
|
||||
"Fields in the input file are terminated by the given string.",
|
||||
&fields_terminated, &fields_terminated, nullptr, GET_STR, REQUIRED_ARG, 0,
|
||||
0, 0, nullptr, 0, nullptr},
|
||||
{"fields-enclosed-by", OPT_ENC,
|
||||
"Fields in the import file are enclosed by the given character.",
|
||||
&enclosed, &enclosed, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"fields-optionally-enclosed-by", OPT_O_ENC,
|
||||
"Fields in the input file are optionally enclosed by the given character.",
|
||||
&opt_enclosed, &opt_enclosed, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"fields-escaped-by", OPT_ESC,
|
||||
"Fields in the input file are escaped by the given character.", &escaped,
|
||||
&escaped, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"force", 'f', "Continue even if we get an SQL error.", &ignore_errors,
|
||||
&ignore_errors, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"help", '?', "Displays this help and exits.", nullptr, nullptr, nullptr,
|
||||
GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"host", 'h', "Connect to host.", ¤t_host, ¤t_host, nullptr,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"ignore", 'i', "If duplicate unique key was found, keep old row.", &ignore,
|
||||
&ignore, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"ignore-lines", OPT_IGN_LINES, "Ignore first n lines of data infile.",
|
||||
&opt_ignore_lines, &opt_ignore_lines, nullptr, GET_LL, REQUIRED_ARG, 0, 0,
|
||||
0, nullptr, 0, nullptr},
|
||||
{"lines-terminated-by", OPT_LTB,
|
||||
"Lines in the input file are terminated by the given string.",
|
||||
&lines_terminated, &lines_terminated, nullptr, GET_STR, REQUIRED_ARG, 0, 0,
|
||||
0, nullptr, 0, nullptr},
|
||||
{"local", 'L', "Read all files through the client.", &opt_local_file,
|
||||
&opt_local_file, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"lock-tables", 'l', "Lock all tables for write (this disables threads).",
|
||||
&lock_tables, &lock_tables, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"low-priority", OPT_LOW_PRIORITY,
|
||||
"Use LOW_PRIORITY when updating the table.", &opt_low_priority,
|
||||
&opt_low_priority, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
#include "client/include/multi_factor_passwordopt-longopts.h"
|
||||
#ifdef _WIN32
|
||||
{"pipe", 'W', "Use named pipes to connect to server.", nullptr, nullptr,
|
||||
nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#endif
|
||||
{"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
|
||||
&opt_plugin_dir, &opt_plugin_dir, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"port", 'P',
|
||||
"Port number to use for connection or 0 for default to, in "
|
||||
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
|
||||
#if MYSQL_PORT_DEFAULT == 0
|
||||
"/etc/services, "
|
||||
#endif
|
||||
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
|
||||
&opt_mysql_port, &opt_mysql_port, nullptr, GET_UINT, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"protocol", OPT_MYSQL_PROTOCOL,
|
||||
"The protocol to use for connection (tcp, socket, pipe, memory).", nullptr,
|
||||
nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"replace", 'r', "If duplicate unique key was found, replace old row.",
|
||||
&replace, &replace, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
#if defined(_WIN32)
|
||||
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
|
||||
"Base name of shared memory.", &shared_memory_base_name,
|
||||
&shared_memory_base_name, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
#endif
|
||||
{"silent", 's', "Be more silent.", &silent, &silent, nullptr, GET_BOOL,
|
||||
NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"socket", 'S', "The socket file to use for connection.",
|
||||
&opt_mysql_unix_port, &opt_mysql_unix_port, nullptr, GET_STR, REQUIRED_ARG,
|
||||
0, 0, 0, nullptr, 0, nullptr},
|
||||
#include "client/include/caching_sha2_passwordopt-longopts.h"
|
||||
#include "client/include/sslopt-longopts.h"
|
||||
|
||||
{"use-threads", OPT_USE_THREADS,
|
||||
"Load files in parallel. The argument is the number "
|
||||
"of threads to use for loading data.",
|
||||
&opt_use_threads, &opt_use_threads, nullptr, GET_UINT, REQUIRED_ARG, 0, 0,
|
||||
0, nullptr, 0, nullptr},
|
||||
{"user", 'u', "User for login if not current user.", ¤t_user,
|
||||
¤t_user, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"verbose", 'v', "Print info about the various stages.", &verbose, &verbose,
|
||||
nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"version", 'V', "Output version information and exit.", nullptr, nullptr,
|
||||
nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"compression-algorithms", 0,
|
||||
"Use compression algorithm in server/client protocol. Valid values "
|
||||
"are any combination of 'zstd','zlib','uncompressed'.",
|
||||
&opt_compress_algorithm, &opt_compress_algorithm, nullptr, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"zstd-compression-level", 0,
|
||||
"Use this compression level in the client/server protocol, in case "
|
||||
"--compression-algorithms=zstd. Valid range is between 1 and 22, "
|
||||
"inclusive. Default is 3.",
|
||||
&opt_zstd_compress_level, &opt_zstd_compress_level, nullptr, GET_UINT,
|
||||
REQUIRED_ARG, 3, 1, 22, nullptr, 0, nullptr},
|
||||
{nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
|
||||
0, nullptr, 0, nullptr}};
|
||||
|
||||
static const char *load_default_groups[] = {"mysqlimport", "client", nullptr};
|
||||
|
||||
static void usage(void) {
|
||||
print_version();
|
||||
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
|
||||
printf(
|
||||
"\
|
||||
Loads tables from text files in various formats. The base name of the\n\
|
||||
text file must be the name of the table that should be used.\n\
|
||||
If one uses sockets to connect to the MySQL server, the server will open and\n\
|
||||
read the text file directly. In other cases the client will open the text\n\
|
||||
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
|
||||
|
||||
printf("\nUsage: %s [OPTIONS] database textfile...", my_progname);
|
||||
print_defaults("my", load_default_groups);
|
||||
my_print_help(my_long_options);
|
||||
my_print_variables(my_long_options);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static bool get_one_option(int optid, const struct my_option *opt,
|
||||
char *argument) {
|
||||
switch (optid) {
|
||||
PARSE_COMMAND_LINE_PASSWORD_OPTION;
|
||||
#ifdef _WIN32
|
||||
case 'W':
|
||||
opt_protocol = MYSQL_PROTOCOL_PIPE;
|
||||
opt_local_file = 1;
|
||||
break;
|
||||
#endif
|
||||
case OPT_ENABLE_CLEARTEXT_PLUGIN:
|
||||
using_opt_enable_cleartext_plugin = true;
|
||||
break;
|
||||
case OPT_MYSQL_PROTOCOL:
|
||||
opt_protocol =
|
||||
find_type_or_exit(argument, &sql_protocol_typelib, opt->name);
|
||||
break;
|
||||
case '#':
|
||||
DBUG_PUSH(argument ? argument : "d:t:o");
|
||||
debug_check_flag = true;
|
||||
break;
|
||||
#include "client/include/sslopt-case.h"
|
||||
|
||||
case 'V':
|
||||
print_version();
|
||||
exit(0);
|
||||
case 'I':
|
||||
case '?':
|
||||
usage();
|
||||
exit(0);
|
||||
case 'C':
|
||||
CLIENT_WARN_DEPRECATED("--compress", "--compression-algorithms");
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
static int get_options(int *argc, char ***argv) {
|
||||
int ho_error;
|
||||
|
||||
if ((ho_error = handle_options(argc, argv, my_long_options, get_one_option)))
|
||||
exit(ho_error);
|
||||
if (debug_info_flag) my_end_arg = MY_CHECK_ERROR | MY_GIVE_INFO;
|
||||
if (debug_check_flag) my_end_arg = MY_CHECK_ERROR;
|
||||
|
||||
if (enclosed && opt_enclosed) {
|
||||
fprintf(stderr,
|
||||
"You can't use ..enclosed.. and ..optionally-enclosed.. at the "
|
||||
"same time.\n");
|
||||
return (1);
|
||||
}
|
||||
if (replace && ignore) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"You can't use --ignore (-i) and --replace (-r) at the same time.\n");
|
||||
return (1);
|
||||
}
|
||||
if (*argc < 2) {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
current_db = *((*argv)++);
|
||||
(*argc)--;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int write_to_table(char *filename, MYSQL *mysql) {
|
||||
char tablename[FN_REFLEN], hard_path[FN_REFLEN],
|
||||
escaped_name[FN_REFLEN * 2 + 1], sql_statement[FN_REFLEN * 16 + 256],
|
||||
escaped_tablename[FN_REFLEN * 2 + 1], *end;
|
||||
DBUG_TRACE;
|
||||
DBUG_PRINT("enter", ("filename: %s", filename));
|
||||
|
||||
fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
|
||||
if (!opt_local_file)
|
||||
my_stpcpy(hard_path, filename);
|
||||
else
|
||||
my_load_path(hard_path, filename, nullptr); /* filename includes the path */
|
||||
|
||||
mysql_real_escape_string_quote(mysql, escaped_tablename, tablename,
|
||||
(unsigned long)strlen(tablename), '`');
|
||||
|
||||
if (opt_delete) {
|
||||
if (verbose)
|
||||
fprintf(stdout, "Deleting the old data from table %s\n", tablename);
|
||||
snprintf(sql_statement, FN_REFLEN * 16 + 256, "DELETE FROM `%s`",
|
||||
escaped_tablename);
|
||||
if (mysql_query(mysql, sql_statement))
|
||||
return db_error_with_table(mysql, tablename);
|
||||
}
|
||||
to_unix_path(hard_path);
|
||||
if (verbose) {
|
||||
if (opt_local_file)
|
||||
fprintf(stdout, "Loading data from LOCAL file: %s into %s\n", hard_path,
|
||||
tablename);
|
||||
else
|
||||
fprintf(stdout, "Loading data from SERVER file: %s into %s\n", hard_path,
|
||||
tablename);
|
||||
}
|
||||
if (opt_local_file)
|
||||
mysql_options(mysql, MYSQL_OPT_LOAD_DATA_LOCAL_DIR, filename);
|
||||
mysql_real_escape_string_quote(mysql, escaped_name, hard_path,
|
||||
(unsigned long)strlen(hard_path), '\'');
|
||||
sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'",
|
||||
opt_low_priority ? "LOW_PRIORITY" : "", opt_local_file ? "LOCAL" : "",
|
||||
escaped_name);
|
||||
end = strend(sql_statement);
|
||||
if (replace) end = my_stpcpy(end, " REPLACE");
|
||||
if (ignore) end = my_stpcpy(end, " IGNORE");
|
||||
end = my_stpcpy(end, " INTO TABLE `");
|
||||
end = my_stpcpy(end, escaped_tablename);
|
||||
end = my_stpcpy(end, "`");
|
||||
|
||||
if (fields_terminated || enclosed || opt_enclosed || escaped)
|
||||
end = my_stpcpy(end, " FIELDS");
|
||||
end = add_load_option(end, fields_terminated, " TERMINATED BY");
|
||||
end = add_load_option(end, enclosed, " ENCLOSED BY");
|
||||
end = add_load_option(end, opt_enclosed, " OPTIONALLY ENCLOSED BY");
|
||||
end = add_load_option(end, escaped, " ESCAPED BY");
|
||||
end = add_load_option(end, lines_terminated, " LINES TERMINATED BY");
|
||||
if (opt_ignore_lines >= 0)
|
||||
end = my_stpcpy(
|
||||
longlong10_to_str(opt_ignore_lines, my_stpcpy(end, " IGNORE "), 10),
|
||||
" LINES");
|
||||
if (opt_columns)
|
||||
end = my_stpcpy(my_stpcpy(my_stpcpy(end, " ("), opt_columns), ")");
|
||||
*end = '\0';
|
||||
|
||||
if (mysql_query(mysql, sql_statement))
|
||||
return db_error_with_table(mysql, tablename);
|
||||
if (!silent) {
|
||||
if (mysql_info(mysql)) /* If NULL-pointer, print nothing */
|
||||
{
|
||||
fprintf(stdout, "%s.%s: %s\n", current_db, tablename, mysql_info(mysql));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lock_table(MYSQL *mysql, int tablecount, char **raw_tablename) {
|
||||
DYNAMIC_STRING query;
|
||||
int i;
|
||||
char tablename[FN_REFLEN];
|
||||
|
||||
if (verbose) fprintf(stdout, "Locking tables for write\n");
|
||||
init_dynamic_string(&query, "LOCK TABLES ", 256);
|
||||
for (i = 0; i < tablecount; i++) {
|
||||
fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
|
||||
dynstr_append(&query, tablename);
|
||||
dynstr_append(&query, " WRITE,");
|
||||
}
|
||||
if (mysql_real_query(mysql, query.str, (ulong)(query.length - 1)))
|
||||
return db_error(mysql); /* We shall continue here, if --force was given */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MYSQL *db_connect(char *host, char *database, char *user, char *) {
|
||||
MYSQL *mysql;
|
||||
if (verbose) fprintf(stdout, "Connecting to %s\n", host ? host : "localhost");
|
||||
if (opt_use_threads && !lock_tables) {
|
||||
native_mutex_lock(&init_mutex);
|
||||
if (!(mysql = mysql_init(nullptr))) {
|
||||
native_mutex_unlock(&init_mutex);
|
||||
return nullptr;
|
||||
}
|
||||
native_mutex_unlock(&init_mutex);
|
||||
} else if (!(mysql = mysql_init(nullptr)))
|
||||
return nullptr;
|
||||
if (opt_compress) mysql_options(mysql, MYSQL_OPT_COMPRESS, NullS);
|
||||
|
||||
if (opt_compress_algorithm)
|
||||
mysql_options(mysql, MYSQL_OPT_COMPRESSION_ALGORITHMS,
|
||||
opt_compress_algorithm);
|
||||
|
||||
mysql_options(mysql, MYSQL_OPT_ZSTD_COMPRESSION_LEVEL,
|
||||
&opt_zstd_compress_level);
|
||||
|
||||
if (SSL_SET_OPTIONS(mysql)) {
|
||||
fprintf(stderr, "%s", SSL_SET_OPTIONS_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
if (opt_protocol)
|
||||
mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char *)&opt_protocol);
|
||||
if (opt_bind_addr) mysql_options(mysql, MYSQL_OPT_BIND, opt_bind_addr);
|
||||
#if defined(_WIN32)
|
||||
if (shared_memory_base_name)
|
||||
mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
|
||||
shared_memory_base_name);
|
||||
#endif
|
||||
|
||||
if (opt_plugin_dir && *opt_plugin_dir)
|
||||
mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
|
||||
|
||||
if (opt_default_auth && *opt_default_auth)
|
||||
mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
||||
|
||||
if (using_opt_enable_cleartext_plugin)
|
||||
mysql_options(mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
|
||||
(char *)&opt_enable_cleartext_plugin);
|
||||
|
||||
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, nullptr);
|
||||
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name",
|
||||
"mysqlimport");
|
||||
set_server_public_key(mysql);
|
||||
set_get_server_public_key_option(mysql);
|
||||
|
||||
set_password_options(mysql);
|
||||
if (!(mysql_real_connect(mysql, host, user, nullptr, database, opt_mysql_port,
|
||||
opt_mysql_unix_port, 0))) {
|
||||
ignore_errors = false; /* NO RETURN FROM db_error */
|
||||
db_error(mysql);
|
||||
if (mysql) mysql_close(mysql);
|
||||
return nullptr;
|
||||
}
|
||||
if (ssl_client_check_post_connect_ssl_setup(
|
||||
mysql, [](const char *err) { fprintf(stderr, "%s\n", err); })) {
|
||||
if (mysql) mysql_close(mysql);
|
||||
return nullptr;
|
||||
}
|
||||
if (verbose) fprintf(stdout, "Selecting database %s\n", database);
|
||||
if (mysql_select_db(mysql, database)) {
|
||||
ignore_errors = false;
|
||||
db_error(mysql);
|
||||
if (mysql) mysql_close(mysql);
|
||||
return nullptr;
|
||||
}
|
||||
return mysql;
|
||||
}
|
||||
|
||||
static void db_disconnect(char *host, MYSQL *mysql) {
|
||||
if (verbose)
|
||||
fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
|
||||
if (mysql) mysql_close(mysql);
|
||||
}
|
||||
|
||||
static int safe_exit(int error) {
|
||||
if (ignore_errors) return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int db_error_with_table(MYSQL *mysql, char *table) {
|
||||
my_printf_error(0, "Error: %d, %s, when using table: %s", MYF(0),
|
||||
mysql_errno(mysql), mysql_error(mysql), table);
|
||||
return safe_exit(1);
|
||||
}
|
||||
|
||||
static int db_error(MYSQL *mysql) {
|
||||
my_printf_error(0, "Error: %d %s", MYF(0), mysql_errno(mysql),
|
||||
mysql_error(mysql));
|
||||
return safe_exit(1);
|
||||
}
|
||||
|
||||
static char *add_load_option(char *ptr, const char *object,
|
||||
const char *statement) {
|
||||
if (object) {
|
||||
/* Don't escape hex constants */
|
||||
if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
|
||||
ptr = strxmov(ptr, " ", statement, " ", object, NullS);
|
||||
else {
|
||||
/* char constant; escape */
|
||||
ptr = strxmov(ptr, " ", statement, " '", NullS);
|
||||
ptr = field_escape(ptr, object, (uint)strlen(object));
|
||||
*ptr++ = '\'';
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allow the user to specify field terminator strings like:
|
||||
** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
|
||||
** This is done by doubleing ' and add a end -\ if needed to avoid
|
||||
** syntax errors from the SQL parser.
|
||||
*/
|
||||
|
||||
static char *field_escape(char *to, const char *from, uint length) {
|
||||
const char *end;
|
||||
uint end_backslashes = 0;
|
||||
|
||||
for (end = from + length; from != end; from++) {
|
||||
*to++ = *from;
|
||||
if (*from == '\\')
|
||||
end_backslashes ^= 1; /* find odd number of backslashes */
|
||||
else {
|
||||
if (*from == '\'' && !end_backslashes)
|
||||
*to++ = *from; /* We want a duplicate of "'" for MySQL */
|
||||
end_backslashes = 0;
|
||||
}
|
||||
}
|
||||
/* Add missing backslashes if user has specified odd number of backs.*/
|
||||
if (end_backslashes) *to++ = '\\';
|
||||
return to;
|
||||
}
|
||||
|
||||
int exitcode = 0;
|
||||
|
||||
extern "C" {
|
||||
static void *worker_thread(void *arg) {
|
||||
int error;
|
||||
char *raw_table_name = (char *)arg;
|
||||
MYSQL *mysql = nullptr;
|
||||
|
||||
if (mysql_thread_init()) goto error;
|
||||
|
||||
if (!(mysql = db_connect(current_host, current_db, current_user,
|
||||
opt_password[0]))) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;") &&
|
||||
(error = db_error(mysql))) {
|
||||
if (exitcode == 0) exitcode = error;
|
||||
/* We shall continue here, if --force was given */
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
We are not currently catching the error here.
|
||||
*/
|
||||
if ((error = write_to_table(raw_table_name, mysql))) {
|
||||
if (exitcode == 0) exitcode = error;
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
if (mysql) db_disconnect(current_host, mysql);
|
||||
native_mutex_lock(&counter_mutex);
|
||||
counter--;
|
||||
native_cond_signal(&count_threshold);
|
||||
native_mutex_unlock(&counter_mutex);
|
||||
mysql_thread_end();
|
||||
my_thread_exit(nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int error = 0;
|
||||
MY_INIT(argv[0]);
|
||||
MYSQL *mysql = nullptr;
|
||||
my_getopt_use_args_separator = true;
|
||||
MEM_ROOT alloc{PSI_NOT_INSTRUMENTED, 512};
|
||||
if (load_defaults("my", load_default_groups, &argc, &argv, &alloc)) return 1;
|
||||
my_getopt_use_args_separator = false;
|
||||
|
||||
if (get_options(&argc, &argv)) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (opt_use_threads && !lock_tables) {
|
||||
char **save_argv;
|
||||
uint worker_thread_count = 0, table_count = 0, i = 0;
|
||||
my_thread_handle *worker_threads; /* Thread descriptor */
|
||||
my_thread_attr_t attr; /* Thread attributes */
|
||||
my_thread_attr_init(&attr);
|
||||
my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
|
||||
|
||||
native_mutex_init(&init_mutex, nullptr);
|
||||
native_mutex_init(&counter_mutex, nullptr);
|
||||
native_cond_init(&count_threshold);
|
||||
|
||||
/* Count the number of tables. This number denotes the total number
|
||||
of threads spawn.
|
||||
*/
|
||||
save_argv = argv;
|
||||
for (table_count = 0; *argv != nullptr; argv++) table_count++;
|
||||
argv = save_argv;
|
||||
|
||||
if (!(worker_threads = (my_thread_handle *)my_malloc(
|
||||
PSI_NOT_INSTRUMENTED, table_count * sizeof(*worker_threads),
|
||||
MYF(0)))) {
|
||||
exitcode = -2;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (counter = 0; *argv != nullptr; argv++) /* Loop through tables */
|
||||
{
|
||||
native_mutex_lock(&counter_mutex);
|
||||
while (counter == opt_use_threads) {
|
||||
struct timespec abstime;
|
||||
|
||||
set_timespec(&abstime, 3);
|
||||
native_cond_timedwait(&count_threshold, &counter_mutex, &abstime);
|
||||
}
|
||||
/* Before exiting the lock we set ourselves up for the next thread */
|
||||
counter++;
|
||||
native_mutex_unlock(&counter_mutex);
|
||||
/* now create the thread */
|
||||
if (my_thread_create(&worker_threads[worker_thread_count], &attr,
|
||||
worker_thread, (void *)*argv) != 0) {
|
||||
native_mutex_lock(&counter_mutex);
|
||||
counter--;
|
||||
native_mutex_unlock(&counter_mutex);
|
||||
fprintf(stderr, "%s: Could not create thread\n", my_progname);
|
||||
continue;
|
||||
}
|
||||
worker_thread_count++;
|
||||
}
|
||||
|
||||
/*
|
||||
We loop until we know that all children have cleaned up.
|
||||
*/
|
||||
native_mutex_lock(&counter_mutex);
|
||||
while (counter) {
|
||||
struct timespec abstime;
|
||||
|
||||
set_timespec(&abstime, 3);
|
||||
native_cond_timedwait(&count_threshold, &counter_mutex, &abstime);
|
||||
}
|
||||
native_mutex_unlock(&counter_mutex);
|
||||
native_mutex_destroy(&init_mutex);
|
||||
native_mutex_destroy(&counter_mutex);
|
||||
native_cond_destroy(&count_threshold);
|
||||
my_thread_attr_destroy(&attr);
|
||||
|
||||
for (i = 0; i < worker_thread_count; i++) {
|
||||
if (my_thread_join(&worker_threads[i], nullptr))
|
||||
fprintf(stderr, "%s: Could not join worker thread.\n", my_progname);
|
||||
}
|
||||
|
||||
my_free(worker_threads);
|
||||
} else {
|
||||
if (!(mysql = db_connect(current_host, current_db, current_user,
|
||||
opt_password[0]))) {
|
||||
exitcode = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (mysql_query(mysql,
|
||||
"/*!40101 set @@character_set_database=binary */;") &&
|
||||
(error = db_error(mysql))) {
|
||||
if (exitcode == 0) exitcode = error;
|
||||
/* We shall continue here, if --force was given */
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (lock_tables && (error = lock_table(mysql, argc, argv))) {
|
||||
if (exitcode == 0) exitcode = error;
|
||||
goto end;
|
||||
}
|
||||
for (; *argv != nullptr; argv++)
|
||||
if ((error = write_to_table(*argv, mysql))) {
|
||||
if (exitcode == 0) exitcode = error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
end:
|
||||
db_disconnect(current_host, mysql);
|
||||
free_passwords();
|
||||
#if defined(_WIN32)
|
||||
my_free(shared_memory_base_name);
|
||||
#endif
|
||||
my_end(my_end_arg);
|
||||
return (exitcode);
|
||||
}
|
872
client/mysqlshow.cc
Normal file
872
client/mysqlshow.cc
Normal file
|
@ -0,0 +1,872 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* Show databases, tables or columns */
|
||||
|
||||
#include <mysql.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "client/include/caching_sha2_passwordopt-vars.h"
|
||||
#include "client/include/client_priv.h"
|
||||
#include "client/include/sslopt-vars.h"
|
||||
#include "compression.h"
|
||||
#include "m_string.h"
|
||||
#include "my_alloc.h"
|
||||
#include "my_dbug.h"
|
||||
#include "my_default.h"
|
||||
#include "my_inttypes.h"
|
||||
#include "my_macros.h"
|
||||
#include "my_sys.h"
|
||||
#include "mysql/service_mysql_alloc.h"
|
||||
#include "mysql/strings/m_ctype.h"
|
||||
#include "nulls.h"
|
||||
#include "print_version.h"
|
||||
#include "strxnmov.h"
|
||||
#include "typelib.h"
|
||||
#include "welcome_copyright_notice.h" /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
|
||||
|
||||
static char *host = nullptr, *user = nullptr;
|
||||
static bool opt_show_keys = false, opt_compress = false, opt_count = false,
|
||||
opt_status = false;
|
||||
static bool opt_table_type = false;
|
||||
static bool debug_info_flag = false, debug_check_flag = false;
|
||||
static uint my_end_arg = 0;
|
||||
static uint opt_verbose = 0;
|
||||
static const char *default_charset = MYSQL_AUTODETECT_CHARSET_NAME;
|
||||
static char *opt_plugin_dir = nullptr, *opt_default_auth = nullptr;
|
||||
static uint opt_enable_cleartext_plugin = 0;
|
||||
static bool using_opt_enable_cleartext_plugin = false;
|
||||
|
||||
static uint opt_zstd_compress_level = default_zstd_compression_level;
|
||||
static char *opt_compress_algorithm = nullptr;
|
||||
|
||||
#include "client/include/multi_factor_passwordopt-vars.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
static char *shared_memory_base_name = nullptr;
|
||||
#endif
|
||||
static uint opt_protocol = 0;
|
||||
static char *opt_bind_addr = nullptr;
|
||||
|
||||
static void get_options(int *argc, char ***argv);
|
||||
static uint opt_mysql_port = 0;
|
||||
static int list_dbs(MYSQL *mysql, const char *wild);
|
||||
static int list_tables(MYSQL *mysql, const char *db, const char *table);
|
||||
static int list_table_status(MYSQL *mysql, const char *db, const char *table);
|
||||
static int list_fields(MYSQL *mysql, const char *db, const char *table,
|
||||
const char *field);
|
||||
static void print_header(const char *header, size_t head_length, ...);
|
||||
static void print_row(const char *header, size_t head_length, ...);
|
||||
static void print_trailer(size_t length, ...);
|
||||
static void print_res_header(MYSQL_RES *result);
|
||||
static void print_res_top(MYSQL_RES *result);
|
||||
static void print_res_row(MYSQL_RES *result, MYSQL_ROW cur);
|
||||
|
||||
static const char *load_default_groups[] = {"mysqlshow", "client", nullptr};
|
||||
static char *opt_mysql_unix_port = nullptr;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int error;
|
||||
bool first_argument_uses_wildcards = false;
|
||||
char *wild;
|
||||
MYSQL mysql;
|
||||
MY_INIT(argv[0]);
|
||||
|
||||
my_getopt_use_args_separator = true;
|
||||
MEM_ROOT alloc{PSI_NOT_INSTRUMENTED, 512};
|
||||
if (load_defaults("my", load_default_groups, &argc, &argv, &alloc)) exit(1);
|
||||
my_getopt_use_args_separator = false;
|
||||
|
||||
get_options(&argc, &argv);
|
||||
|
||||
wild = nullptr;
|
||||
if (argc) {
|
||||
char *pos = argv[argc - 1], *to;
|
||||
for (to = pos; *pos; pos++, to++) {
|
||||
switch (*pos) {
|
||||
case '*':
|
||||
*pos = '%';
|
||||
first_argument_uses_wildcards = true;
|
||||
break;
|
||||
case '?':
|
||||
*pos = '_';
|
||||
first_argument_uses_wildcards = true;
|
||||
break;
|
||||
case '%':
|
||||
case '_':
|
||||
first_argument_uses_wildcards = true;
|
||||
break;
|
||||
case '\\':
|
||||
pos++;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*to = *pos;
|
||||
}
|
||||
*to = *pos; /* just to copy a '\0' if '\\' was used */
|
||||
}
|
||||
if (first_argument_uses_wildcards)
|
||||
wild = argv[--argc];
|
||||
else if (argc == 3) /* We only want one field */
|
||||
wild = argv[--argc];
|
||||
|
||||
if (argc > 2) {
|
||||
fprintf(stderr, "%s: Too many arguments\n", my_progname);
|
||||
exit(1);
|
||||
}
|
||||
mysql_init(&mysql);
|
||||
if (opt_compress) mysql_options(&mysql, MYSQL_OPT_COMPRESS, NullS);
|
||||
if (SSL_SET_OPTIONS(&mysql)) {
|
||||
fprintf(stderr, "%s", SSL_SET_OPTIONS_ERROR);
|
||||
exit(1);
|
||||
}
|
||||
if (opt_protocol)
|
||||
mysql_options(&mysql, MYSQL_OPT_PROTOCOL, (char *)&opt_protocol);
|
||||
if (opt_bind_addr) mysql_options(&mysql, MYSQL_OPT_BIND, opt_bind_addr);
|
||||
#if defined(_WIN32)
|
||||
if (shared_memory_base_name)
|
||||
mysql_options(&mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
|
||||
shared_memory_base_name);
|
||||
#endif
|
||||
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
|
||||
|
||||
if (opt_compress_algorithm)
|
||||
mysql_options(&mysql, MYSQL_OPT_COMPRESSION_ALGORITHMS,
|
||||
opt_compress_algorithm);
|
||||
|
||||
mysql_options(&mysql, MYSQL_OPT_ZSTD_COMPRESSION_LEVEL,
|
||||
&opt_zstd_compress_level);
|
||||
|
||||
if (opt_plugin_dir && *opt_plugin_dir)
|
||||
mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
|
||||
|
||||
if (opt_default_auth && *opt_default_auth)
|
||||
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
|
||||
|
||||
if (using_opt_enable_cleartext_plugin)
|
||||
mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
|
||||
(char *)&opt_enable_cleartext_plugin);
|
||||
|
||||
mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, nullptr);
|
||||
mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name",
|
||||
"mysqlshow");
|
||||
set_server_public_key(&mysql);
|
||||
set_get_server_public_key_option(&mysql);
|
||||
set_password_options(&mysql);
|
||||
if (!(mysql_real_connect(&mysql, host, user, nullptr,
|
||||
(first_argument_uses_wildcards) ? "" : argv[0],
|
||||
opt_mysql_port, opt_mysql_unix_port, 0))) {
|
||||
fprintf(stderr, "%s: %s\n", my_progname, mysql_error(&mysql));
|
||||
exit(1);
|
||||
}
|
||||
if (ssl_client_check_post_connect_ssl_setup(
|
||||
&mysql, [](const char *err) { fprintf(stderr, "%s\n", err); })) {
|
||||
mysql_close(&mysql);
|
||||
free_passwords();
|
||||
mysql_server_end();
|
||||
my_end(my_end_arg);
|
||||
exit(1);
|
||||
}
|
||||
switch (argc) {
|
||||
case 0:
|
||||
error = list_dbs(&mysql, wild);
|
||||
break;
|
||||
case 1:
|
||||
if (opt_status)
|
||||
error = list_table_status(&mysql, argv[0], wild);
|
||||
else
|
||||
error = list_tables(&mysql, argv[0], wild);
|
||||
break;
|
||||
default:
|
||||
if (opt_status && !wild)
|
||||
error = list_table_status(&mysql, argv[0], argv[1]);
|
||||
else
|
||||
error = list_fields(&mysql, argv[0], argv[1], wild);
|
||||
break;
|
||||
}
|
||||
mysql_close(&mysql); /* Close & free connection */
|
||||
free_passwords();
|
||||
#if defined(_WIN32)
|
||||
my_free(shared_memory_base_name);
|
||||
#endif
|
||||
mysql_server_end();
|
||||
my_end(my_end_arg);
|
||||
exit(error ? 1 : 0);
|
||||
}
|
||||
|
||||
static struct my_option my_long_options[] = {
|
||||
{"bind-address", 0, "IP address to bind to.", (uchar **)&opt_bind_addr,
|
||||
(uchar **)&opt_bind_addr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr,
|
||||
0, nullptr},
|
||||
{"character-sets-dir", 'c', "Directory for character set files.",
|
||||
&charsets_dir, &charsets_dir, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"default-character-set", OPT_DEFAULT_CHARSET,
|
||||
"Set the default character set.", &default_charset, &default_charset,
|
||||
nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"count", OPT_COUNT,
|
||||
"Show number of rows per table (may be slow for non-MyISAM tables).",
|
||||
&opt_count, &opt_count, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"compress", 'C', "Use compression in server/client protocol.",
|
||||
&opt_compress, &opt_compress, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr,
|
||||
0, nullptr},
|
||||
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", nullptr,
|
||||
nullptr, nullptr, GET_STR, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"debug-check", OPT_DEBUG_CHECK,
|
||||
"Check memory and open file usage at exit.", &debug_check_flag,
|
||||
&debug_check_flag, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
|
||||
&debug_info_flag, &debug_info_flag, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"default_auth", OPT_DEFAULT_AUTH,
|
||||
"Default authentication client-side plugin to use.", &opt_default_auth,
|
||||
&opt_default_auth, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
|
||||
"Enable/disable the clear text authentication plugin.",
|
||||
&opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin, nullptr,
|
||||
GET_BOOL, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"help", '?', "Display this help and exit.", nullptr, nullptr, nullptr,
|
||||
GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"host", 'h', "Connect to host.", &host, &host, nullptr, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"status", 'i', "Shows a lot of extra information about each table.",
|
||||
&opt_status, &opt_status, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"keys", 'k', "Show keys for table.", &opt_show_keys, &opt_show_keys,
|
||||
nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#include "client/include/multi_factor_passwordopt-longopts.h"
|
||||
{"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
|
||||
&opt_plugin_dir, &opt_plugin_dir, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
{"port", 'P',
|
||||
"Port number to use for connection or 0 for default to, in "
|
||||
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
|
||||
#if MYSQL_PORT_DEFAULT == 0
|
||||
"/etc/services, "
|
||||
#endif
|
||||
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
|
||||
&opt_mysql_port, &opt_mysql_port, nullptr, GET_UINT, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
#ifdef _WIN32
|
||||
{"pipe", 'W', "Use named pipes to connect to server.", nullptr, nullptr,
|
||||
nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#endif
|
||||
{"protocol", OPT_MYSQL_PROTOCOL,
|
||||
"The protocol to use for connection (tcp, socket, pipe, memory).", nullptr,
|
||||
nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
#if defined(_WIN32)
|
||||
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
|
||||
"Base name of shared memory.", &shared_memory_base_name,
|
||||
&shared_memory_base_name, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0,
|
||||
nullptr, 0, nullptr},
|
||||
#endif
|
||||
{"show-table-type", 't', "Show table type column.", &opt_table_type,
|
||||
&opt_table_type, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"socket", 'S', "The socket file to use for connection.",
|
||||
&opt_mysql_unix_port, &opt_mysql_unix_port, nullptr, GET_STR, REQUIRED_ARG,
|
||||
0, 0, 0, nullptr, 0, nullptr},
|
||||
#include "client/include/caching_sha2_passwordopt-longopts.h"
|
||||
#include "client/include/sslopt-longopts.h"
|
||||
|
||||
{"user", 'u', "User for login if not current user.", &user, &user, nullptr,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"verbose", 'v',
|
||||
"More verbose output; you can use this multiple times to get even more "
|
||||
"verbose output.",
|
||||
nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
|
||||
nullptr},
|
||||
{"version", 'V', "Output version information and exit.", nullptr, nullptr,
|
||||
nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"compression-algorithms", 0,
|
||||
"Use compression algorithm in server/client protocol. Valid values "
|
||||
"are any combination of 'zstd','zlib','uncompressed'.",
|
||||
&opt_compress_algorithm, &opt_compress_algorithm, nullptr, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
|
||||
{"zstd-compression-level", 0,
|
||||
"Use this compression level in the client/server protocol, in case "
|
||||
"--compression-algorithms=zstd. Valid range is between 1 and 22, "
|
||||
"inclusive. Default is 3.",
|
||||
&opt_zstd_compress_level, &opt_zstd_compress_level, nullptr, GET_UINT,
|
||||
REQUIRED_ARG, 3, 1, 22, nullptr, 0, nullptr},
|
||||
{nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
|
||||
0, nullptr, 0, nullptr}};
|
||||
|
||||
static void usage(void) {
|
||||
print_version();
|
||||
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
|
||||
puts(
|
||||
"Shows the structure of a MySQL database (databases, tables, and "
|
||||
"columns).\n");
|
||||
printf("Usage: %s [OPTIONS] [database [table [column]]]\n", my_progname);
|
||||
puts(
|
||||
"\n\
|
||||
If last argument contains a shell or SQL wildcard (*,?,% or _) then only\n\
|
||||
what\'s matched by the wildcard is shown.\n\
|
||||
If no database is given then all matching databases are shown.\n\
|
||||
If no table is given, then all matching tables in database are shown.\n\
|
||||
If no column is given, then all matching columns and column types in table\n\
|
||||
are shown.");
|
||||
print_defaults("my", load_default_groups);
|
||||
my_print_help(my_long_options);
|
||||
my_print_variables(my_long_options);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static bool get_one_option(int optid, const struct my_option *opt,
|
||||
char *argument) {
|
||||
switch (optid) {
|
||||
case 'v':
|
||||
opt_verbose++;
|
||||
break;
|
||||
PARSE_COMMAND_LINE_PASSWORD_OPTION;
|
||||
case 'W':
|
||||
#ifdef _WIN32
|
||||
opt_protocol = MYSQL_PROTOCOL_PIPE;
|
||||
#endif
|
||||
break;
|
||||
case (int)OPT_ENABLE_CLEARTEXT_PLUGIN:
|
||||
using_opt_enable_cleartext_plugin = true;
|
||||
break;
|
||||
case OPT_MYSQL_PROTOCOL:
|
||||
opt_protocol =
|
||||
find_type_or_exit(argument, &sql_protocol_typelib, opt->name);
|
||||
break;
|
||||
case '#':
|
||||
DBUG_PUSH(argument ? argument : "d:t:o");
|
||||
debug_check_flag = true;
|
||||
break;
|
||||
#include "client/include/sslopt-case.h"
|
||||
|
||||
case 'V':
|
||||
print_version();
|
||||
exit(0);
|
||||
case '?':
|
||||
case 'I': /* Info */
|
||||
usage();
|
||||
exit(0);
|
||||
case 'C':
|
||||
CLIENT_WARN_DEPRECATED("--compress", "--compression-algorithms");
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
static void get_options(int *argc, char ***argv) {
|
||||
int ho_error;
|
||||
|
||||
if ((ho_error = handle_options(argc, argv, my_long_options, get_one_option)))
|
||||
exit(ho_error);
|
||||
|
||||
if (opt_count) {
|
||||
/*
|
||||
We need to set verbose to 2 as we need to change the output to include
|
||||
the number-of-rows column
|
||||
*/
|
||||
opt_verbose = 2;
|
||||
}
|
||||
if (debug_info_flag) my_end_arg = MY_CHECK_ERROR | MY_GIVE_INFO;
|
||||
if (debug_check_flag) my_end_arg = MY_CHECK_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
static int list_dbs(MYSQL *mysql, const char *wild) {
|
||||
const char *header;
|
||||
size_t length = 0;
|
||||
uint counter = 0;
|
||||
ulong rowcount = 0L;
|
||||
char tables[NAME_LEN + 1], rows[NAME_LEN + 1];
|
||||
char query[NAME_LEN + 100];
|
||||
MYSQL_FIELD *field;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row = nullptr, rrow;
|
||||
|
||||
if (!(result = mysql_list_dbs(mysql, wild))) {
|
||||
fprintf(stderr, "%s: Cannot list databases: %s\n", my_progname,
|
||||
mysql_error(mysql));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
If a wildcard was used, but there was only one row and it's name is an
|
||||
exact match, we'll assume they really wanted to see the contents of that
|
||||
database. This is because it is fairly common for database names to
|
||||
contain the underscore (_), like INFORMATION_SCHEMA.
|
||||
*/
|
||||
if (wild && mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
if (!my_strcasecmp(&my_charset_latin1, row[0], wild)) {
|
||||
mysql_free_result(result);
|
||||
if (opt_status)
|
||||
return list_table_status(mysql, wild, nullptr);
|
||||
else
|
||||
return list_tables(mysql, wild, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (wild) printf("Wildcard: %s\n", wild);
|
||||
|
||||
header = "Databases";
|
||||
length = strlen(header);
|
||||
field = mysql_fetch_field(result);
|
||||
if (length < field->max_length) length = field->max_length;
|
||||
|
||||
if (!opt_verbose)
|
||||
print_header(header, length, NullS);
|
||||
else if (opt_verbose == 1)
|
||||
print_header(header, length, "Tables", 6, NullS);
|
||||
else
|
||||
print_header(header, length, "Tables", 6, "Total Rows", 12, NullS);
|
||||
|
||||
/* The first row may have already been read up above. */
|
||||
while (row || (row = mysql_fetch_row(result))) {
|
||||
counter++;
|
||||
|
||||
if (opt_verbose) {
|
||||
if (!(mysql_select_db(mysql, row[0]))) {
|
||||
MYSQL_RES *tresult = mysql_list_tables(mysql, (char *)nullptr);
|
||||
if (mysql_affected_rows(mysql) > 0) {
|
||||
sprintf(tables, "%6lu", (ulong)mysql_affected_rows(mysql));
|
||||
rowcount = 0;
|
||||
if (opt_verbose > 1) {
|
||||
/* Print the count of tables and rows for each database */
|
||||
MYSQL_ROW trow;
|
||||
while ((trow = mysql_fetch_row(tresult))) {
|
||||
snprintf(query, sizeof(query), "SELECT COUNT(*) FROM `%s`",
|
||||
trow[0]);
|
||||
if (!(mysql_query(mysql, query))) {
|
||||
MYSQL_RES *rresult;
|
||||
if ((rresult = mysql_store_result(mysql))) {
|
||||
rrow = mysql_fetch_row(rresult);
|
||||
rowcount += (ulong)my_strtoull(rrow[0], (char **)nullptr, 10);
|
||||
mysql_free_result(rresult);
|
||||
}
|
||||
}
|
||||
}
|
||||
sprintf(rows, "%12lu", rowcount);
|
||||
}
|
||||
} else {
|
||||
sprintf(tables, "%6d", 0);
|
||||
sprintf(rows, "%12d", 0);
|
||||
}
|
||||
mysql_free_result(tresult);
|
||||
} else {
|
||||
my_stpcpy(tables, "N/A");
|
||||
my_stpcpy(rows, "N/A");
|
||||
}
|
||||
}
|
||||
|
||||
if (!opt_verbose)
|
||||
print_row(row[0], length, 0);
|
||||
else if (opt_verbose == 1)
|
||||
print_row(row[0], length, tables, 6, NullS);
|
||||
else
|
||||
print_row(row[0], length, tables, 6, rows, 12, NullS);
|
||||
|
||||
row = nullptr;
|
||||
}
|
||||
|
||||
print_trailer(length, (opt_verbose > 0 ? 6 : 0), (opt_verbose > 1 ? 12 : 0),
|
||||
0);
|
||||
|
||||
if (counter && opt_verbose)
|
||||
printf("%u row%s in set.\n", counter, (counter > 1) ? "s" : "");
|
||||
mysql_free_result(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int list_tables(MYSQL *mysql, const char *db, const char *table) {
|
||||
const char *header;
|
||||
size_t head_length;
|
||||
uint counter = 0;
|
||||
char query[2 * NAME_LEN + 100], rows[2 * NAME_LEN + 2], fields[16];
|
||||
MYSQL_FIELD *field;
|
||||
MYSQL_RES *result = nullptr;
|
||||
MYSQL_ROW row, rrow;
|
||||
|
||||
if (mysql_select_db(mysql, db)) {
|
||||
fprintf(stderr, "%s: Cannot connect to db %s: %s\n", my_progname, db,
|
||||
mysql_error(mysql));
|
||||
return 1;
|
||||
}
|
||||
if (table) {
|
||||
/*
|
||||
We just hijack the 'rows' variable for a bit to store the escaped
|
||||
table name
|
||||
*/
|
||||
mysql_real_escape_string_quote(mysql, rows, table,
|
||||
(unsigned long)strlen(table), '\'');
|
||||
snprintf(query, sizeof(query), "show%s tables like '%s'",
|
||||
opt_table_type ? " full" : "", rows);
|
||||
} else
|
||||
snprintf(query, sizeof(query), "show%s tables",
|
||||
opt_table_type ? " full" : "");
|
||||
if (mysql_query(mysql, query) || !(result = mysql_store_result(mysql))) {
|
||||
fprintf(stderr, "%s: Cannot list tables in %s: %s\n", my_progname, db,
|
||||
mysql_error(mysql));
|
||||
exit(1);
|
||||
}
|
||||
printf("Database: %s", db);
|
||||
if (table) printf(" Wildcard: %s", table);
|
||||
putchar('\n');
|
||||
|
||||
header = "Tables";
|
||||
head_length = strlen(header);
|
||||
field = mysql_fetch_field(result);
|
||||
if (head_length < field->max_length) head_length = field->max_length;
|
||||
|
||||
if (opt_table_type) {
|
||||
if (!opt_verbose)
|
||||
print_header(header, head_length, "table_type", 10, NullS);
|
||||
else if (opt_verbose == 1)
|
||||
print_header(header, head_length, "table_type", 10, "Columns", 8, NullS);
|
||||
else {
|
||||
print_header(header, head_length, "table_type", 10, "Columns", 8,
|
||||
"Total Rows", 10, NullS);
|
||||
}
|
||||
} else {
|
||||
if (!opt_verbose)
|
||||
print_header(header, head_length, NullS);
|
||||
else if (opt_verbose == 1)
|
||||
print_header(header, head_length, "Columns", 8, NullS);
|
||||
else
|
||||
print_header(header, head_length, "Columns", 8, "Total Rows", 10, NullS);
|
||||
}
|
||||
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
counter++;
|
||||
if (opt_verbose > 0) {
|
||||
if (!(mysql_select_db(mysql, db))) {
|
||||
mysql_real_escape_string_quote(mysql, rows, row[0],
|
||||
(unsigned long)strlen(row[0]), '`');
|
||||
snprintf(query, sizeof(query), "SELECT * FROM `%s` LIMIT 0", rows);
|
||||
MYSQL_RES *rresult = (0 == mysql_query(mysql, query))
|
||||
? mysql_store_result(mysql)
|
||||
: nullptr;
|
||||
ulong rowcount = 0L;
|
||||
if (!rresult) {
|
||||
my_stpcpy(fields, "N/A");
|
||||
my_stpcpy(rows, "N/A");
|
||||
} else {
|
||||
sprintf(fields, "%8u", (uint)mysql_num_fields(rresult));
|
||||
mysql_free_result(rresult);
|
||||
|
||||
if (opt_verbose > 1) {
|
||||
/* Print the count of rows for each table */
|
||||
snprintf(query, sizeof(query), "SELECT COUNT(*) FROM `%s`", row[0]);
|
||||
if (!(mysql_query(mysql, query))) {
|
||||
if ((rresult = mysql_store_result(mysql))) {
|
||||
rrow = mysql_fetch_row(rresult);
|
||||
rowcount +=
|
||||
(unsigned long)my_strtoull(rrow[0], (char **)nullptr, 10);
|
||||
mysql_free_result(rresult);
|
||||
}
|
||||
sprintf(rows, "%10lu", rowcount);
|
||||
} else
|
||||
sprintf(rows, "%10d", 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
my_stpcpy(fields, "N/A");
|
||||
my_stpcpy(rows, "N/A");
|
||||
}
|
||||
}
|
||||
if (opt_table_type) {
|
||||
if (!opt_verbose)
|
||||
print_row(row[0], head_length, row[1], 10, NullS);
|
||||
else if (opt_verbose == 1)
|
||||
print_row(row[0], head_length, row[1], 10, fields, 8, NullS);
|
||||
else
|
||||
print_row(row[0], head_length, row[1], 10, fields, 8, rows, 10, NullS);
|
||||
} else {
|
||||
if (!opt_verbose)
|
||||
print_row(row[0], head_length, NullS);
|
||||
else if (opt_verbose == 1)
|
||||
print_row(row[0], head_length, fields, 8, NullS);
|
||||
else
|
||||
print_row(row[0], head_length, fields, 8, rows, 10, NullS);
|
||||
}
|
||||
}
|
||||
|
||||
print_trailer(
|
||||
head_length,
|
||||
(opt_table_type ? 10
|
||||
: opt_verbose > 0 ? 8
|
||||
: 0),
|
||||
(opt_table_type ? (opt_verbose > 0 ? 8 : 0) : (opt_verbose > 1 ? 10 : 0)),
|
||||
!opt_table_type ? 0
|
||||
: opt_verbose > 1 ? 10
|
||||
: 0,
|
||||
0);
|
||||
|
||||
if (counter && opt_verbose)
|
||||
printf("%u row%s in set.\n\n", counter, (counter > 1) ? "s" : "");
|
||||
|
||||
mysql_free_result(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int list_table_status(MYSQL *mysql, const char *db, const char *wild) {
|
||||
char query[NAME_LEN + 100];
|
||||
size_t len;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
len = sizeof(query);
|
||||
len -= snprintf(query, len, "show table status from `%s`", db);
|
||||
if (wild && wild[0] && len)
|
||||
strxnmov(query + strlen(query), len - 1, " like '", wild, "'", NullS);
|
||||
if (mysql_query(mysql, query) || !(result = mysql_store_result(mysql))) {
|
||||
fprintf(stderr, "%s: Cannot get status for db: %s, table: %s: %s\n",
|
||||
my_progname, db, wild ? wild : "", mysql_error(mysql));
|
||||
if (mysql_errno(mysql) == ER_PARSE_ERROR)
|
||||
fprintf(stderr,
|
||||
"This error probably means that your MySQL server doesn't "
|
||||
"support the\n\'show table status' command.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Database: %s", db);
|
||||
if (wild) printf(" Wildcard: %s", wild);
|
||||
putchar('\n');
|
||||
|
||||
print_res_header(result);
|
||||
while ((row = mysql_fetch_row(result))) print_res_row(result, row);
|
||||
print_res_top(result);
|
||||
mysql_free_result(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
list fields uses field interface as an example of how to parse
|
||||
a MYSQL FIELD
|
||||
*/
|
||||
|
||||
static int list_fields(MYSQL *mysql, const char *db, const char *table,
|
||||
const char *wild) {
|
||||
char query[NAME_LEN + 100];
|
||||
size_t len;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
ulong rows = 0;
|
||||
|
||||
if (mysql_select_db(mysql, db)) {
|
||||
fprintf(stderr, "%s: Cannot connect to db: %s: %s\n", my_progname, db,
|
||||
mysql_error(mysql));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (opt_count) {
|
||||
snprintf(query, sizeof(query), "select count(*) from `%s`", table);
|
||||
if (mysql_query(mysql, query) || !(result = mysql_store_result(mysql))) {
|
||||
fprintf(stderr, "%s: Cannot get record count for db: %s, table: %s: %s\n",
|
||||
my_progname, db, table, mysql_error(mysql));
|
||||
return 1;
|
||||
}
|
||||
row = mysql_fetch_row(result);
|
||||
rows = (ulong)my_strtoull(row[0], (char **)nullptr, 10);
|
||||
mysql_free_result(result);
|
||||
}
|
||||
|
||||
len = sizeof(query);
|
||||
len -= snprintf(query, len, "show /*!32332 FULL */ columns from `%s`", table);
|
||||
if (wild && wild[0] && len)
|
||||
strxnmov(query + strlen(query), len - 1, " like '", wild, "'", NullS);
|
||||
if (mysql_query(mysql, query) || !(result = mysql_store_result(mysql))) {
|
||||
fprintf(stderr, "%s: Cannot list columns in db: %s, table: %s: %s\n",
|
||||
my_progname, db, table, mysql_error(mysql));
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Database: %s Table: %s", db, table);
|
||||
if (opt_count) printf(" Rows: %lu", rows);
|
||||
if (wild && wild[0]) printf(" Wildcard: %s", wild);
|
||||
putchar('\n');
|
||||
|
||||
print_res_header(result);
|
||||
while ((row = mysql_fetch_row(result))) print_res_row(result, row);
|
||||
print_res_top(result);
|
||||
mysql_free_result(result);
|
||||
if (opt_show_keys) {
|
||||
snprintf(query, sizeof(query), "show keys from `%s`", table);
|
||||
if (mysql_query(mysql, query) || !(result = mysql_store_result(mysql))) {
|
||||
fprintf(stderr, "%s: Cannot list keys in db: %s, table: %s: %s\n",
|
||||
my_progname, db, table, mysql_error(mysql));
|
||||
return 1;
|
||||
}
|
||||
if (mysql_num_rows(result)) {
|
||||
print_res_header(result);
|
||||
while ((row = mysql_fetch_row(result))) print_res_row(result, row);
|
||||
print_res_top(result);
|
||||
} else
|
||||
puts("Table has no keys");
|
||||
mysql_free_result(result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
General functions to print a nice ascii-table from data
|
||||
*****************************************************************************/
|
||||
|
||||
static void print_header(const char *header, size_t head_length, ...) {
|
||||
va_list args;
|
||||
size_t length, i, str_length, pre_space;
|
||||
const char *field;
|
||||
|
||||
va_start(args, head_length);
|
||||
putchar('+');
|
||||
field = header;
|
||||
length = head_length;
|
||||
for (;;) {
|
||||
for (i = 0; i < length + 2; i++) putchar('-');
|
||||
putchar('+');
|
||||
if (!(field = va_arg(args, char *))) break;
|
||||
length = va_arg(args, uint);
|
||||
}
|
||||
va_end(args);
|
||||
putchar('\n');
|
||||
|
||||
va_start(args, head_length);
|
||||
field = header;
|
||||
length = head_length;
|
||||
putchar('|');
|
||||
for (;;) {
|
||||
str_length = strlen(field);
|
||||
if (str_length > length) str_length = length + 1;
|
||||
pre_space = ((length - str_length) / 2) + 1;
|
||||
for (i = 0; i < pre_space; i++) putchar(' ');
|
||||
for (i = 0; i < str_length; i++) putchar(field[i]);
|
||||
length = length + 2 - str_length - pre_space;
|
||||
for (i = 0; i < length; i++) putchar(' ');
|
||||
putchar('|');
|
||||
if (!(field = va_arg(args, char *))) break;
|
||||
length = va_arg(args, uint);
|
||||
}
|
||||
va_end(args);
|
||||
putchar('\n');
|
||||
|
||||
va_start(args, head_length);
|
||||
putchar('+');
|
||||
field = header;
|
||||
length = head_length;
|
||||
for (;;) {
|
||||
for (i = 0; i < length + 2; i++) putchar('-');
|
||||
putchar('+');
|
||||
if (!(field = va_arg(args, char *))) break;
|
||||
length = va_arg(args, uint);
|
||||
}
|
||||
va_end(args);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void print_row(const char *header, size_t head_length, ...) {
|
||||
va_list args;
|
||||
const char *field;
|
||||
size_t i, length, field_length;
|
||||
|
||||
va_start(args, head_length);
|
||||
field = header;
|
||||
length = head_length;
|
||||
for (;;) {
|
||||
putchar('|');
|
||||
putchar(' ');
|
||||
fputs(field, stdout);
|
||||
field_length = strlen(field);
|
||||
for (i = field_length; i <= length; i++) putchar(' ');
|
||||
if (!(field = va_arg(args, char *))) break;
|
||||
length = va_arg(args, uint);
|
||||
}
|
||||
va_end(args);
|
||||
putchar('|');
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void print_trailer(size_t head_length, ...) {
|
||||
va_list args;
|
||||
size_t length, i;
|
||||
|
||||
va_start(args, head_length);
|
||||
length = head_length;
|
||||
putchar('+');
|
||||
for (;;) {
|
||||
for (i = 0; i < length + 2; i++) putchar('-');
|
||||
putchar('+');
|
||||
if (!(length = va_arg(args, uint))) break;
|
||||
}
|
||||
va_end(args);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void print_res_header(MYSQL_RES *result) {
|
||||
MYSQL_FIELD *field;
|
||||
|
||||
print_res_top(result);
|
||||
mysql_field_seek(result, 0);
|
||||
putchar('|');
|
||||
while ((field = mysql_fetch_field(result))) {
|
||||
printf(" %-*s|", (int)field->max_length + 1, field->name);
|
||||
}
|
||||
putchar('\n');
|
||||
print_res_top(result);
|
||||
}
|
||||
|
||||
static void print_res_top(MYSQL_RES *result) {
|
||||
uint i, length;
|
||||
MYSQL_FIELD *field;
|
||||
|
||||
putchar('+');
|
||||
mysql_field_seek(result, 0);
|
||||
while ((field = mysql_fetch_field(result))) {
|
||||
if ((length = strlen(field->name)) > field->max_length)
|
||||
field->max_length = length;
|
||||
else
|
||||
length = field->max_length;
|
||||
for (i = length + 2; i-- > 0;) putchar('-');
|
||||
putchar('+');
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void print_res_row(MYSQL_RES *result, MYSQL_ROW cur) {
|
||||
uint i, length;
|
||||
MYSQL_FIELD *field;
|
||||
putchar('|');
|
||||
mysql_field_seek(result, 0);
|
||||
for (i = 0; i < mysql_num_fields(result); i++) {
|
||||
field = mysql_fetch_field(result);
|
||||
length = field->max_length;
|
||||
printf(" %-*s|", length + 1, cur[i] ? (char *)cur[i] : "");
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
2074
client/mysqlslap.cc
Normal file
2074
client/mysqlslap.cc
Normal file
File diff suppressed because it is too large
Load diff
11544
client/mysqltest.cc
Normal file
11544
client/mysqltest.cc
Normal file
File diff suppressed because it is too large
Load diff
77
client/mysqltest/error.h
Normal file
77
client/mysqltest/error.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
#ifndef ERROR_INCLUDED
|
||||
#define ERROR_INCLUDED
|
||||
|
||||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
/// @file
|
||||
///
|
||||
/// This file declares the Error class.
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "mysql_com.h" // SQLSTATE_LENGTH
|
||||
|
||||
enum error_type { ERR_ERRNO = 1, ERR_SQLSTATE };
|
||||
|
||||
/// Class representing an error.
|
||||
///
|
||||
/// Contains following information
|
||||
/// * Error code
|
||||
/// * Error type
|
||||
/// * SQLSTATE
|
||||
///
|
||||
/// If an error type value is
|
||||
/// * ERR_ERRNO, then SQLSTATE value is "00000"
|
||||
/// * ERR_SQLSTATE, then error code value is 0
|
||||
class Error {
|
||||
public:
|
||||
Error(std::uint32_t error_code, const char *sqlstate, error_type type) {
|
||||
this->m_error_code = error_code;
|
||||
this->m_type = type;
|
||||
std::strcpy(this->m_sqlstate, sqlstate);
|
||||
}
|
||||
|
||||
/// Return a sqlstate for an error.
|
||||
///
|
||||
/// @retval SQLSTATE string
|
||||
const char *sqlstate() { return m_sqlstate; }
|
||||
|
||||
/// Return an error code
|
||||
///
|
||||
/// @retval Error code
|
||||
std::uint32_t error_code() { return m_error_code; }
|
||||
|
||||
/// Return an error type
|
||||
///
|
||||
/// @retval Error type (ERR_ERRNO or ERR_SQLSTATE)
|
||||
error_type type() { return m_type; }
|
||||
|
||||
private:
|
||||
std::uint32_t m_error_code;
|
||||
error_type m_type;
|
||||
char m_sqlstate[SQLSTATE_LENGTH + 1]; // '\0' terminated string
|
||||
};
|
||||
|
||||
#endif // ERROR_INCLUDED
|
53
client/mysqltest/error_names.cc
Normal file
53
client/mysqltest/error_names.cc
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include "client/mysqltest/error_names.h"
|
||||
|
||||
static st_error global_error_names[] = {
|
||||
{"<No error>", static_cast<int>(-1), "", nullptr, nullptr, 0},
|
||||
#ifndef IN_DOXYGEN
|
||||
#include "mysqlclient_ername.h"
|
||||
#include "mysqld_ername.h"
|
||||
#endif /* IN_DOXYGEN */
|
||||
{nullptr, 0, nullptr, nullptr, nullptr, 0}};
|
||||
|
||||
int get_errcode_from_name(std::string error_name) {
|
||||
for (st_error *error = global_error_names; error->name; error++) {
|
||||
if (error_name.compare(error->name) == 0) return error->error_code;
|
||||
}
|
||||
|
||||
// Unknown SQL error name, return -1
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *get_errname_from_code(int error_code) {
|
||||
// Return an empty string if error code is 0.
|
||||
if (!error_code) return "";
|
||||
|
||||
for (st_error *error = global_error_names; error->error_code; error++) {
|
||||
if (error->error_code == error_code) return error->name;
|
||||
}
|
||||
|
||||
// Unknown SQL error code, return "<Unknown>" keyword.
|
||||
return "<Unknown>";
|
||||
}
|
53
client/mysqltest/error_names.h
Normal file
53
client/mysqltest/error_names.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
#ifndef ERROR_NAMES_INCLUDED
|
||||
#define ERROR_NAMES_INCLUDED
|
||||
|
||||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include <string>
|
||||
|
||||
struct st_error {
|
||||
const char *name;
|
||||
int error_code;
|
||||
const char *description;
|
||||
const char *odbc_state;
|
||||
const char *jdbc_state;
|
||||
unsigned int error_index;
|
||||
};
|
||||
|
||||
/// Get an error code from an error name string.
|
||||
///
|
||||
/// @param error_name Error name string
|
||||
///
|
||||
/// @retval -1 if error name is unknown, error code otherwise.
|
||||
int get_errcode_from_name(std::string error_name);
|
||||
|
||||
/// Get an error name from an error code.
|
||||
///
|
||||
/// @param error_code Error code
|
||||
///
|
||||
/// @retval "<Unknown>" keyword if error code is unknown, error name
|
||||
/// otherwise.
|
||||
const char *get_errname_from_code(int error_code);
|
||||
|
||||
#endif // ERROR_NAMES_INCLUDED
|
56
client/mysqltest/expected_errors.cc
Normal file
56
client/mysqltest/expected_errors.cc
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include "client/mysqltest/expected_errors.h"
|
||||
|
||||
std::string Expected_errors::error_list() {
|
||||
std::string error_list("");
|
||||
|
||||
for (std::size_t i = 0; i < m_errors.size(); i++) {
|
||||
if (i > 0) error_list.append(",");
|
||||
if (m_errors.at(i)->type() == ERR_ERRNO)
|
||||
error_list.append(std::to_string(m_errors.at(i)->error_code()));
|
||||
else
|
||||
error_list.append(m_errors.at(i)->sqlstate());
|
||||
}
|
||||
|
||||
return error_list;
|
||||
}
|
||||
|
||||
std::vector<unsigned int> Expected_errors::errors() {
|
||||
std::vector<unsigned int> errors;
|
||||
for (std::size_t i = 0; i < m_errors.size(); i++) {
|
||||
errors.push_back(m_errors.at(i)->error_code());
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
void Expected_errors::add_error(const char *sqlstate, error_type type) {
|
||||
std::unique_ptr<Error> new_error(new Error(0, sqlstate, type));
|
||||
m_errors.push_back(std::move(new_error));
|
||||
}
|
||||
|
||||
void Expected_errors::add_error(std::uint32_t error_code, error_type type) {
|
||||
std::unique_ptr<Error> new_error(new Error(error_code, "00000", type));
|
||||
m_errors.push_back(std::move(new_error));
|
||||
}
|
97
client/mysqltest/expected_errors.h
Normal file
97
client/mysqltest/expected_errors.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
#ifndef EXPECTED_ERRORS_INCLUDED
|
||||
#define EXPECTED_ERRORS_INCLUDED
|
||||
|
||||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include "client/mysqltest/error.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define MAX_ERROR_COUNT 20
|
||||
|
||||
/// Class representing a list of error codes passed as argument to
|
||||
/// mysqltest command <code>--error</code>.
|
||||
class Expected_errors {
|
||||
public:
|
||||
typedef std::vector<std::unique_ptr<Error>>::iterator iterator;
|
||||
|
||||
Expected_errors() = default;
|
||||
~Expected_errors() = default;
|
||||
|
||||
iterator begin() { return m_errors.begin(); }
|
||||
iterator end() { return m_errors.end(); }
|
||||
|
||||
/// Return a sqlstate of the first error in the list.
|
||||
///
|
||||
/// @retval SQLSTATE string
|
||||
const char *sqlstate() { return m_errors[0]->sqlstate(); }
|
||||
|
||||
/// Return an error type of the first error in the list.
|
||||
///
|
||||
/// @retval Error type (ERR_ERRNO or ERR_SQLSTATE)
|
||||
error_type type() { return m_errors[0]->type(); }
|
||||
|
||||
/// Return length of the list containing errors.
|
||||
///
|
||||
/// @retval Length value
|
||||
std::size_t count() { return m_errors.size(); }
|
||||
|
||||
/// Return list of error codes
|
||||
///
|
||||
/// @retval List of error codes
|
||||
std::string error_list();
|
||||
|
||||
/// Return list of error codes in the list
|
||||
///
|
||||
/// @retval List of error codes
|
||||
std::vector<std::uint32_t> errors();
|
||||
|
||||
/// Return an error code of the first error in the list.
|
||||
///
|
||||
/// @retval Error code
|
||||
unsigned int error_code() { return m_errors[0]->error_code(); }
|
||||
|
||||
/// Add a new error to the existing list of errors.
|
||||
///
|
||||
/// @param sqlstate SQLSTATE string
|
||||
/// @param type Error type
|
||||
void add_error(const char *sqlstate, error_type type);
|
||||
|
||||
/// Add a new error to the existing list of errors.
|
||||
///
|
||||
/// @param error_code Error number
|
||||
/// @param type Error type
|
||||
void add_error(std::uint32_t error_code, error_type type);
|
||||
|
||||
/// Delete all errors from the vector.
|
||||
void clear_list() { m_errors.clear(); }
|
||||
|
||||
private:
|
||||
// List containing expected errors
|
||||
std::vector<std::unique_ptr<Error>> m_errors;
|
||||
};
|
||||
|
||||
#endif // EXPECTED_ERRORS_INCLUDED
|
71
client/mysqltest/expected_warnings.cc
Normal file
71
client/mysqltest/expected_warnings.cc
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include "client/mysqltest/expected_warnings.h"
|
||||
|
||||
void Expected_warnings::add_warning(std::uint32_t warning_code,
|
||||
const char *warning_name,
|
||||
bool once_property) {
|
||||
for (std::size_t i = 0; i < m_warnings.size(); i++) {
|
||||
// Warning already exist, don't add it.
|
||||
if (m_warnings.at(i)->warning_code() == warning_code) return;
|
||||
}
|
||||
|
||||
// Add a new warning to the existing list.
|
||||
std::unique_ptr<Warning> new_warning(
|
||||
new Warning(warning_code, warning_name, once_property));
|
||||
m_warnings.push_back(std::move(new_warning));
|
||||
}
|
||||
|
||||
void Expected_warnings::remove_warning(std::uint32_t error_code,
|
||||
bool once_property) {
|
||||
for (std::size_t i = 0; i < m_warnings.size(); i++) {
|
||||
if (m_warnings.at(i)->warning_code() == error_code) {
|
||||
if (once_property)
|
||||
m_warnings.at(i)->set_ignore_warning(true);
|
||||
else
|
||||
m_warnings.erase(begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Expected_warnings::update_list() {
|
||||
for (std::size_t i = 0; i < m_warnings.size(); i++) {
|
||||
if (m_warnings.at(i)->expired()) {
|
||||
m_warnings.erase(begin() + i);
|
||||
i--;
|
||||
} else if (m_warnings.at(i)->ignore_warning()) {
|
||||
m_warnings.at(i)->set_ignore_warning(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string Expected_warnings::warnings_list() {
|
||||
std::string warnings;
|
||||
for (std::size_t i = 0; i < m_warnings.size(); i++) {
|
||||
if (i > 0) warnings.append(",");
|
||||
warnings.append(m_warnings.at(i)->warning_name());
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
91
client/mysqltest/expected_warnings.h
Normal file
91
client/mysqltest/expected_warnings.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
#ifndef EXPECTED_WARNINGS_INCLUDED
|
||||
#define EXPECTED_WARNINGS_INCLUDED
|
||||
|
||||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include "client/mysqltest/warning.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
/// Class representing any one of the following list.
|
||||
/// * List of disabled warnings
|
||||
/// * List of enabled warnings
|
||||
class Expected_warnings {
|
||||
public:
|
||||
typedef std::vector<std::unique_ptr<Warning>>::iterator iterator;
|
||||
|
||||
Expected_warnings() = default;
|
||||
~Expected_warnings() = default;
|
||||
|
||||
iterator begin() { return m_warnings.begin(); }
|
||||
iterator end() { return m_warnings.end(); }
|
||||
|
||||
/// Return length of the list containing warnings.
|
||||
///
|
||||
/// @retval Length value
|
||||
std::size_t count() { return m_warnings.size(); }
|
||||
|
||||
/// Delete all warnings from the vector.
|
||||
void clear_list() { m_warnings.clear(); }
|
||||
|
||||
/// Add a new warning to the existing list of warnings only if it
|
||||
/// doesn't exist.
|
||||
///
|
||||
/// @param warning_code Warning number
|
||||
/// @param warning_name Warning name
|
||||
/// @param once_property Flag value representing the scope of a warning.
|
||||
void add_warning(std::uint32_t warning_code, const char *warning_name,
|
||||
bool once_property);
|
||||
|
||||
/// Remove a warning from the existing list of warnings if it exists.
|
||||
/// If "ONCE" argument is specified, don't remove the warning, set a
|
||||
/// flag to ignore disabling or enabling of it for the next statement
|
||||
/// only.
|
||||
///
|
||||
/// @param warning_code Warning number
|
||||
/// @param once_property Flag value representing the scope of a
|
||||
/// disabled warning
|
||||
void remove_warning(std::uint32_t warning_code, bool once_property);
|
||||
|
||||
/// Update the list of disabled or enabled warnings.
|
||||
///
|
||||
/// * Remove all the warnings which are disabled or enabled only for
|
||||
/// one statement. These warnings are expired after the execution of
|
||||
/// next statement.
|
||||
///
|
||||
/// * Reset ignore_warning flag value to 0 if it set to 1.
|
||||
void update_list();
|
||||
|
||||
/// Return a list of symbolic names of disabled or enabled warnings.
|
||||
///
|
||||
/// @retval String containing symbolic names of disabled warnings
|
||||
std::string warnings_list();
|
||||
|
||||
private:
|
||||
// List containing disabled or enabled warnings.
|
||||
std::vector<std::unique_ptr<Warning>> m_warnings;
|
||||
};
|
||||
|
||||
#endif // EXPECTED_WARNINGS_INCLUDED
|
122
client/mysqltest/logfile.cc
Normal file
122
client/mysqltest/logfile.cc
Normal file
|
@ -0,0 +1,122 @@
|
|||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include "client/mysqltest/logfile.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
Logfile::Logfile() : m_file(nullptr), m_bytes_written(0) {
|
||||
std::memset(m_filename, 0, sizeof(m_filename));
|
||||
}
|
||||
|
||||
bool Logfile::flush() {
|
||||
if (m_file && std::fflush(m_file)) {
|
||||
// Flush failed, thrown an error.
|
||||
std::cerr << "Failed to flush the contents to file '" << m_filename
|
||||
<< "': " << std::strerror(errno) << ", errno: " << errno
|
||||
<< std::endl;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Logfile::open(const char *dirname, const char *filename, const char *ext) {
|
||||
if (!filename) {
|
||||
m_file = stdout;
|
||||
} else {
|
||||
fn_format(m_filename, filename, dirname, ext,
|
||||
*dirname ? MY_REPLACE_DIR | MY_REPLACE_EXT : MY_REPLACE_EXT);
|
||||
|
||||
this->close();
|
||||
|
||||
// Open a file, print an error message if the operation fails.
|
||||
if ((m_file = std::fopen(m_filename, "wb+")) == nullptr) {
|
||||
std::cerr << "Failed to open log file '" << m_filename
|
||||
<< "': " << std::strerror(errno) << ", errno: " << errno
|
||||
<< std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Logfile::write(const char *data, std::size_t length) {
|
||||
if (length > 0) {
|
||||
if (std::fwrite(data, 1, length, m_file) != length) {
|
||||
std::cerr << "Failed to write " << length << "bytes to '" << m_filename
|
||||
<< "': " << std::strerror(errno) << ", errno: " << errno
|
||||
<< std::endl;
|
||||
return true;
|
||||
}
|
||||
m_bytes_written += length;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Logfile::close() {
|
||||
if (m_file) {
|
||||
if (m_file == stdout)
|
||||
std::fflush(m_file);
|
||||
else
|
||||
std::fclose(m_file);
|
||||
}
|
||||
m_file = nullptr;
|
||||
}
|
||||
|
||||
void Logfile::show_tail(unsigned int lines) {
|
||||
if (!m_file || m_file == stdout || lines == 0) return;
|
||||
|
||||
// Move to end of the file.
|
||||
if (std::fseek(m_file, 0, SEEK_END) != 0) {
|
||||
std::cerr << "fseek() failed: " << std::strerror(errno)
|
||||
<< ", errno: " << errno << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int position = std::ftell(m_file);
|
||||
unsigned int count = 0;
|
||||
|
||||
while (position) {
|
||||
std::fseek(m_file, --position, SEEK_SET);
|
||||
// Read one character at a time, and stop reading when N number of
|
||||
// newline characters are found.
|
||||
if ((std::fgetc(m_file) == '\n') && (count++ == lines)) break;
|
||||
}
|
||||
|
||||
std::cerr << std::endl
|
||||
<< "The result from queries just before the failure was:"
|
||||
<< std::endl;
|
||||
|
||||
char buffer[256];
|
||||
std::size_t bytes;
|
||||
if (count <= lines) std::fseek(m_file, 0L, SEEK_SET);
|
||||
while ((bytes = std::fread(buffer, 1, sizeof(buffer), m_file)) > 0) {
|
||||
if (std::fwrite(buffer, 1, bytes, stderr) != bytes)
|
||||
std::cerr << "fwrite failed: " << std::strerror(errno)
|
||||
<< ", errno: " << errno << std::endl;
|
||||
}
|
||||
|
||||
std::fflush(stderr);
|
||||
}
|
89
client/mysqltest/logfile.h
Normal file
89
client/mysqltest/logfile.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
#ifndef LOGFILE_INCLUDED
|
||||
#define LOGFILE_INCLUDED
|
||||
|
||||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
/// @file
|
||||
///
|
||||
/// This file declares the Log file class.
|
||||
|
||||
#include "my_io.h"
|
||||
#include "my_sys.h"
|
||||
|
||||
class Logfile {
|
||||
public:
|
||||
Logfile();
|
||||
Logfile(const Logfile &) = default;
|
||||
|
||||
virtual ~Logfile() { close(); }
|
||||
|
||||
/// Return file name.
|
||||
///
|
||||
/// @retval Name of the file.
|
||||
const char *file_name() const { return m_filename; }
|
||||
|
||||
/// Return number bytes written into a log file.
|
||||
///
|
||||
/// @retval Number bytes written into a log file.
|
||||
std::size_t bytes_written() const { return m_bytes_written; }
|
||||
|
||||
/// Flush any unwritten content from the stream's buffer to the
|
||||
/// associated file.
|
||||
///
|
||||
/// @retval False if successful, true otherwise.
|
||||
bool flush();
|
||||
|
||||
/// Construct a file path using directory name, file name and extension
|
||||
/// arguments and open it in write/update mode.
|
||||
///
|
||||
/// @param dirname Directory name
|
||||
/// @param filename File name
|
||||
/// @param ext Extension name
|
||||
///
|
||||
/// @retval False if successful, true otherwise.
|
||||
bool open(const char *dirname, const char *filename, const char *ext);
|
||||
|
||||
/// Write the contents in data array to a file.
|
||||
///
|
||||
/// @param data Pointer to the array to be written
|
||||
/// @param length Length of the buffer
|
||||
///
|
||||
/// @retval False if successful, true otherwise.
|
||||
bool write(const char *data, std::size_t length);
|
||||
|
||||
/// Print the last N number of lines from a file to stderr.
|
||||
///
|
||||
/// @param lines Number of lines
|
||||
void show_tail(unsigned int lines);
|
||||
|
||||
private:
|
||||
/// Close the given file stream.
|
||||
void close();
|
||||
|
||||
char m_filename[FN_REFLEN];
|
||||
FILE *m_file;
|
||||
std::size_t m_bytes_written;
|
||||
};
|
||||
|
||||
#endif // LOGFILE_INCLUDED
|
264
client/mysqltest/regular_expressions.cc
Normal file
264
client/mysqltest/regular_expressions.cc
Normal file
|
@ -0,0 +1,264 @@
|
|||
/* Copyright (c) 2019, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "client/mysqltest/regular_expressions.h"
|
||||
|
||||
#include "my_compiler.h"
|
||||
#include "mysql/strings/m_ctype.h"
|
||||
|
||||
[[noreturn]] extern void die(const char *fmt, ...)
|
||||
MY_ATTRIBUTE((format(printf, 1, 2)));
|
||||
|
||||
/*
|
||||
Filter for queries that can be run using the
|
||||
MySQL Prepared Statements C API.
|
||||
*/
|
||||
static const char *const ps_re_str =
|
||||
"^("
|
||||
"[[:space:]]*REPLACE[[:space:]]|"
|
||||
"[[:space:]]*INSERT[[:space:]]|"
|
||||
"[[:space:]]*UPDATE[[:space:]]|"
|
||||
"[[:space:]]*DELETE[[:space:]]|"
|
||||
"[[:space:]]*SELECT[[:space:]]|"
|
||||
"[[:space:]]*CREATE[[:space:]]+DATABASE[[:space:]]|"
|
||||
"[[:space:]]*CREATE[[:space:]]+INDEX[[:space:]]|"
|
||||
"[[:space:]]*CREATE[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*CREATE[[:space:]]+USER[[:space:]]|"
|
||||
"[[:space:]]*CREATE[[:space:]]+TEMPORARY[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*DROP[[:space:]]+DATABASE[[:space:]]|"
|
||||
"[[:space:]]*DROP[[:space:]]+INDEX[[:space:]]|"
|
||||
"[[:space:]]*DROP[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*DROP[[:space:]]+USER[[:space:]]|"
|
||||
"[[:space:]]*DROP[[:space:]]+VIEW[[:space:]]|"
|
||||
"[[:space:]]*DROP[[:space:]]+TEMPORARY[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*ALTER[[:space:]]+USER[[:space:]]|"
|
||||
"[[:space:]]*RENAME[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*RENAME[[:space:]]+USER[[:space:]]|"
|
||||
"[[:space:]]*TRUNCATE[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*ANALYZE[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*CHECKSUM[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*CHECKSUM[[:space:]]+TABLES[[:space:]]|"
|
||||
"[[:space:]]*OPTIMIZE[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*REPAIR[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*GRANT[[:space:]]|"
|
||||
"[[:space:]]*KILL[[:space:]]|"
|
||||
"[[:space:]]*REVOKE[[:space:]]+ALL[[:space:]]+PRIVILEGES[[:space:]]|"
|
||||
"[[:space:]]*DO[[:space:]]|"
|
||||
"[[:space:]]*CALL[[:space:]]|"
|
||||
"[[:space:]]*COMMIT[[:space:]]|"
|
||||
"[[:space:]]*SET[[:space:]]+OPTION[[:space:]]|"
|
||||
"[[:space:]]*SHOW[[:space:]]+CREATE[[:space:]]+TABLE[[:space:]]|"
|
||||
"[[:space:]]*SHOW[[:space:]]+CREATE[[:space:]]+PROCEDURE[[:space:]]|"
|
||||
"[[:space:]]*SHOW[[:space:]]+CREATE[[:space:]]+FUNCTION[[:space:]]|"
|
||||
"[[:space:]]*SHOW[[:space:]]+CREATE[[:space:]]+VIEW[[:space:]]|"
|
||||
"[[:space:]]*SHOW[[:space:]]+CREATE[[:space:]]+EVENT[[:space:]]|"
|
||||
"[[:space:]]*INSTALL[[:space:]]+PLUGIN[[:space:]]|"
|
||||
"[[:space:]]*UNINSTALL[[:space:]]+PLUGIN[[:space:]]|"
|
||||
"[[:space:]]*RESET[[:space:]]+MASTER[[:space:]]|"
|
||||
"[[:space:]]*RESET[[:space:]]+SLAVE[[:space:]]|"
|
||||
"[[:space:]]*RESET[[:space:]]+QUERY[[:space:]]+CACHE[[:space:]]|"
|
||||
"[[:space:]]*SHOW[[:space:]]+BINLOG[[:space:]]+EVENTS[[:space:]]|"
|
||||
"[[:space:]]*SHOW[[:space:]]+MASTER[[:space:]]+LOGS[[:space:]]|"
|
||||
"[[:space:]]*SHOW[[:space:]]+MASTER[[:space:]]+STATUS[[:space:]]|"
|
||||
"[[:space:]]*SHOW[[:space:]]+BINARY[[:space:]]+LOGS[[:space:]]|"
|
||||
"[[:space:]]*SHOW[[:space:]]+SLAVE[[:space:]]+STATUS[[:space:]]|"
|
||||
"[[:space:]]*SLAVE[[:space:]]+START[[:space:]]|"
|
||||
"[[:space:]]*SLAVE[[:space:]]+STOP[[:space:]]|"
|
||||
"[[:space:]]*DELETE[[:space:]]+MULTI[[:space:]]|"
|
||||
"[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|"
|
||||
"[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])";
|
||||
|
||||
/*
|
||||
Filter for queries that can be run using the
|
||||
Stored procedures.
|
||||
*/
|
||||
static const char *const sp_re_str = ps_re_str;
|
||||
|
||||
/*
|
||||
Filter for queries that can be run as views.
|
||||
*/
|
||||
static const char *const view_re_str =
|
||||
"^("
|
||||
"[[:space:]]*SELECT[[:space:]])";
|
||||
|
||||
const char *const opt_trace_re_str =
|
||||
"^("
|
||||
"[[:space:]]*INSERT[[:space:]]|"
|
||||
"[[:space:]]*UPDATE[[:space:]]|"
|
||||
"[[:space:]]*DELETE[[:space:]]|"
|
||||
"[[:space:]]*EXPLAIN[[:space:]]|"
|
||||
"[[:space:]]*SELECT[[:space:]])";
|
||||
|
||||
/* Filter for queries that can be converted to EXPLAIN. */
|
||||
static const char *const explain_re_str =
|
||||
"^("
|
||||
"[[:space:]]*(SELECT|DELETE|UPDATE|INSERT|REPLACE)[[:space:]])";
|
||||
|
||||
/* Precompiled regular expressions. */
|
||||
std::regex ps_re(ps_re_str,
|
||||
std::regex_constants::nosubs | std::regex_constants::icase);
|
||||
std::regex sp_re(sp_re_str,
|
||||
std::regex_constants::nosubs | std::regex_constants::icase);
|
||||
std::regex view_re(view_re_str,
|
||||
std::regex_constants::nosubs | std::regex_constants::icase);
|
||||
std::regex opt_trace_re(opt_trace_re_str, std::regex_constants::nosubs |
|
||||
std::regex_constants::icase);
|
||||
std::regex explain_re(explain_re_str, std::regex_constants::nosubs |
|
||||
std::regex_constants::icase);
|
||||
|
||||
extern CHARSET_INFO *charset_info;
|
||||
|
||||
/**
|
||||
Execute all substitutions on val.
|
||||
|
||||
@param[in] val Pointer to the character string to be used as
|
||||
input for the regex replace operation.
|
||||
@param[in,out] r Pointer to the st_replace_regex structure which
|
||||
holds arguments and information for the command.
|
||||
@param[in,out] len Pointer to variable holding length of input string.
|
||||
|
||||
@retval True If substituition was made.
|
||||
@retval False If no substituition was made.
|
||||
|
||||
@note
|
||||
r->buf points at the resulting buffer with all substitutions done.
|
||||
len points at length of resulting buffer.
|
||||
r->even_buf and r->odd_buf might have been reallocated.
|
||||
r->even_buf_len and r->odd_buf_len might have been changed.
|
||||
|
||||
@todo
|
||||
At some point figure out if there is a way to do everything in one pass.
|
||||
*/
|
||||
int multi_reg_replace(struct st_replace_regex *r, char *val, size_t *len) {
|
||||
size_t i;
|
||||
char *in_buf, *out_buf;
|
||||
int *buf_len_p;
|
||||
|
||||
in_buf = val;
|
||||
out_buf = r->even_buf;
|
||||
buf_len_p = &r->even_buf_len;
|
||||
r->buf = nullptr;
|
||||
|
||||
/*
|
||||
For each substitution, perform replacement only if the input buffer
|
||||
is not empty.
|
||||
*/
|
||||
if (*len > 0) {
|
||||
for (i = 0; i < r->regex_arr.size(); i++) {
|
||||
try {
|
||||
struct st_regex re(r->regex_arr[i]);
|
||||
char *save_out_buf = out_buf;
|
||||
|
||||
std::regex rpat(re.pattern, (re.icase == 0)
|
||||
? std::regex_constants::ECMAScript
|
||||
: std::regex_constants::icase);
|
||||
|
||||
std::string sin = std::string(in_buf, *len);
|
||||
std::string sout;
|
||||
|
||||
/*
|
||||
We use iterators instead of using the input buffer directly as
|
||||
it may include the null character (0x00) and characters succeeding
|
||||
them will be ignored unless we specify the start and end positions
|
||||
of the input string explicitly.
|
||||
*/
|
||||
std::regex_replace(std::back_inserter(sout), sin.begin(), sin.end(),
|
||||
rpat, re.replace, std::regex_constants::format_sed);
|
||||
|
||||
/*
|
||||
If some replacement is performed, write the replaced string into the
|
||||
output buffer.
|
||||
*/
|
||||
if (sout.compare(sin) != 0) {
|
||||
*len = sout.length();
|
||||
if (*len >= (uint)*buf_len_p) {
|
||||
uint need_buf_len = (*len) + 1;
|
||||
out_buf = (char *)my_realloc(PSI_NOT_INSTRUMENTED, out_buf,
|
||||
need_buf_len, MYF(MY_WME + MY_FAE));
|
||||
*buf_len_p = need_buf_len;
|
||||
}
|
||||
|
||||
// Copy result to output buffer.
|
||||
strncpy(out_buf, sout.c_str(), *len + 1);
|
||||
|
||||
// If the buffer has been reallocated, make adjustments
|
||||
if (save_out_buf != out_buf) {
|
||||
if (save_out_buf == r->even_buf)
|
||||
r->even_buf = out_buf;
|
||||
else
|
||||
r->odd_buf = out_buf;
|
||||
}
|
||||
|
||||
r->buf = out_buf;
|
||||
if (in_buf == val) in_buf = r->odd_buf;
|
||||
|
||||
std::swap(in_buf, out_buf);
|
||||
|
||||
buf_len_p =
|
||||
(out_buf == r->even_buf) ? &r->even_buf_len : &r->odd_buf_len;
|
||||
}
|
||||
} catch (const std::regex_error &e) {
|
||||
die("Error in replace_regex for `/%s/%s/` : %s",
|
||||
(r->regex_arr[i]).pattern, (r->regex_arr[i]).replace, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (r->buf == nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
Function to check if a protocol's regular expression matches the query
|
||||
string.
|
||||
|
||||
@param re Pointer to a precompiled regular expression.
|
||||
@param str Pointer to character string in which the pattern needs to be
|
||||
searched.
|
||||
|
||||
@retval 1 If the pattern is found.
|
||||
@retval 0 If the pattern is not found.
|
||||
*/
|
||||
int search_protocol_re(std::regex *re, const char *str) {
|
||||
while (my_isspace(charset_info, *str)) str++;
|
||||
if (str[0] == '/' && str[1] == '*') {
|
||||
const char *comm_end = strstr(str, "*/");
|
||||
if (!comm_end) die("Statement is unterminated comment");
|
||||
str = comm_end + 2;
|
||||
}
|
||||
|
||||
// Check if statement matches the pattern string
|
||||
if (std::regex_search(str, *re, std::regex_constants::match_continuous)) {
|
||||
/*
|
||||
Simulate the "[^;]*$" check which follows the SQL prefix
|
||||
in the regex used to filter statements to be run with ps/
|
||||
sp protocol as using it directly in the regex is currently
|
||||
not possible due to an issue in the standard regex library.
|
||||
*/
|
||||
if ((re == &ps_re || re == &sp_re) && strchr(str, ';') != nullptr) return 0;
|
||||
|
||||
// Match found
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
66
client/mysqltest/regular_expressions.h
Normal file
66
client/mysqltest/regular_expressions.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Copyright (c) 2019, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef REGULAR_EXPRESSIONS_INCLUDED
|
||||
#define REGULAR_EXPRESSIONS_INCLUDED
|
||||
|
||||
#include <regex>
|
||||
|
||||
#include "mysql/components/services/bits/psi_bits.h"
|
||||
#include "prealloced_array.h"
|
||||
|
||||
extern std::regex explain_re;
|
||||
extern std::regex opt_trace_re;
|
||||
extern std::regex ps_re;
|
||||
extern std::regex sp_re;
|
||||
extern std::regex view_re;
|
||||
|
||||
struct st_regex {
|
||||
char *pattern; /* Pattern to be replaced */
|
||||
char *replace; /* String or expression to replace the pattern with */
|
||||
int icase; /* true if the match is case insensitive */
|
||||
};
|
||||
|
||||
struct st_replace_regex {
|
||||
st_replace_regex() : regex_arr(PSI_NOT_INSTRUMENTED) {}
|
||||
/* stores a list of st_regex subsitutions */
|
||||
Prealloced_array<st_regex, 128> regex_arr;
|
||||
|
||||
/*
|
||||
Temporary storage areas for substitutions. To reduce unnessary copying
|
||||
and memory freeing/allocation, we pre-allocate two buffers, and alternate
|
||||
their use, one for input/one for output, the roles changing on the next
|
||||
st_regex substitution. At the end of substitutions, buf points to the
|
||||
one containing the final result.
|
||||
*/
|
||||
char *buf{nullptr};
|
||||
char *even_buf{nullptr};
|
||||
char *odd_buf{nullptr};
|
||||
int even_buf_len{0};
|
||||
int odd_buf_len{0};
|
||||
};
|
||||
|
||||
int multi_reg_replace(struct st_replace_regex *r, char *val, size_t *len);
|
||||
int search_protocol_re(std::regex *re, const char *str);
|
||||
|
||||
#endif // REGULAR_EXPRESSIONS_INCLUDED
|
93
client/mysqltest/secondary_engine.cc
Normal file
93
client/mysqltest/secondary_engine.cc
Normal file
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include "client/mysqltest/secondary_engine.h"
|
||||
#include "client/mysqltest/error_names.h"
|
||||
#include "client/mysqltest/utils.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
static int offload_count_after = 0;
|
||||
static int offload_count_before = 0;
|
||||
|
||||
/// Get secondary engine execution count value.
|
||||
//
|
||||
/// @param mysql mysql handle
|
||||
/// @param mode Mode value (either "after" or "before")
|
||||
///
|
||||
/// @retval True if the query fails, false otherwise.
|
||||
bool Secondary_engine::offload_count(MYSQL *mysql, const char *mode) {
|
||||
std::string offload_count;
|
||||
|
||||
const char *query =
|
||||
"SHOW GLOBAL STATUS LIKE 'Secondary_engine_execution_count'";
|
||||
|
||||
if (query_get_string(mysql, query, 1, &offload_count)) {
|
||||
int error = mysql_errno(mysql);
|
||||
if (error == 0 || error == 1104 || error == 2006) return false;
|
||||
std::cerr << "mysqltest: Query '" << query << "' failed, ERROR " << error
|
||||
<< " (" << mysql_sqlstate(mysql) << "): " << mysql_error(mysql)
|
||||
<< std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!std::strcmp(mode, "before")) {
|
||||
offload_count_before = get_int_val(offload_count.c_str());
|
||||
} else if (!std::strcmp(mode, "after")) {
|
||||
if (!offload_count_after) {
|
||||
offload_count_after = get_int_val(offload_count.c_str());
|
||||
} else {
|
||||
offload_count_after =
|
||||
offload_count_after + get_int_val(offload_count.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Report secondary engine execution count value.
|
||||
///
|
||||
/// @param filename File to store the count value
|
||||
void Secondary_engine::report_offload_count(const char *filename) {
|
||||
if (!offload_count_after && offload_count_after < offload_count_before)
|
||||
offload_count_after = offload_count_before;
|
||||
|
||||
int count_val = offload_count_after - offload_count_before;
|
||||
assert(count_val >= 0);
|
||||
|
||||
std::ofstream report_file(filename, std::ios::out);
|
||||
|
||||
if (report_file.is_open()) {
|
||||
std::string count = std::to_string(count_val);
|
||||
report_file << count << std::endl;
|
||||
}
|
||||
|
||||
report_file.close();
|
||||
}
|
51
client/mysqltest/secondary_engine.h
Normal file
51
client/mysqltest/secondary_engine.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#ifndef SECONDARY_ENGINE_INCLUDED
|
||||
#define SECONDARY_ENGINE_INCLUDED
|
||||
|
||||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "mysql.h"
|
||||
|
||||
class Secondary_engine {
|
||||
public:
|
||||
Secondary_engine() = default;
|
||||
~Secondary_engine() = default;
|
||||
|
||||
/// Get the secondary engine execution count value.
|
||||
///
|
||||
/// @param mysql mysql handle
|
||||
/// @param mode Mode value (either "after" or "before")
|
||||
///
|
||||
/// @retval True if the query fails, false otherwise.
|
||||
bool offload_count(MYSQL *mysql, const char *mode);
|
||||
|
||||
/// Report secondary engine execution count value.
|
||||
///
|
||||
/// @param filename File to store the count value
|
||||
void report_offload_count(const char *filename);
|
||||
};
|
||||
|
||||
#endif // SECONDARY_ENGINE_INCLUDED
|
85
client/mysqltest/utils.cc
Normal file
85
client/mysqltest/utils.cc
Normal file
|
@ -0,0 +1,85 @@
|
|||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
#include "client/mysqltest/utils.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
/// Run a query and return one field in the result set from the first
|
||||
/// row and column.
|
||||
///
|
||||
/// @param mysql mysql handle
|
||||
/// @param query Query string
|
||||
/// @param column Column value
|
||||
/// @param str String object to store the rvalue
|
||||
///
|
||||
/// @retval True if fails to get the value, true otherwise.
|
||||
bool query_get_string(MYSQL *mysql, const char *query, int column,
|
||||
std::string *str) {
|
||||
MYSQL_RES *res = nullptr;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (mysql_query(mysql, query)) {
|
||||
mysql_free_result(res);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (((res = mysql_store_result(mysql)) == nullptr) ||
|
||||
((row = mysql_fetch_row(res)) == nullptr)) {
|
||||
mysql_free_result(res);
|
||||
str = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
str->assign(row[column] ? row[column] : "NULL");
|
||||
mysql_free_result(res);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Use stoi function to get the integer value from a string.
|
||||
///
|
||||
/// @param str String which may contain an integer or an alphanumeric
|
||||
/// string.
|
||||
///
|
||||
/// @retval Integer value corresponding to the contents of the string,
|
||||
/// if conversion is successful, or -1 if integer is out of
|
||||
/// range, or if the conversion fails.
|
||||
int get_int_val(const char *str) {
|
||||
int value;
|
||||
std::size_t size;
|
||||
|
||||
try {
|
||||
value = std::stoi(str, &size, 10);
|
||||
if (size != std::strlen(str)) value = -1;
|
||||
} catch (const std::out_of_range &) {
|
||||
std::fprintf(stderr, "Integer value '%s' is out of range. ", str);
|
||||
value = -1;
|
||||
} catch (const std::invalid_argument &) {
|
||||
value = -1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
53
client/mysqltest/utils.h
Normal file
53
client/mysqltest/utils.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
#ifndef UTILS_INCLUDED
|
||||
#define UTILS_INCLUDED
|
||||
|
||||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "mysql.h"
|
||||
|
||||
/// Run a query and return one field in the result set from the first
|
||||
/// row and column.
|
||||
///
|
||||
/// @param mysql mysql handle
|
||||
/// @param query Query string
|
||||
/// @param column Column value
|
||||
/// @param str String object to store the rvalue
|
||||
///
|
||||
/// @retval True if fails to get the value, true otherwise.
|
||||
bool query_get_string(MYSQL *mysql, const char *query, int column,
|
||||
std::string *str);
|
||||
|
||||
/// Use stoi function to get the integer value from a string.
|
||||
///
|
||||
/// @param str String which may contain an integer or an alphanumeric
|
||||
/// string.
|
||||
///
|
||||
/// @retval Integer value corresponding to the contents of the string,
|
||||
/// if conversion is successful, or -1 if integer is out of
|
||||
/// range, or if the conversion fails.
|
||||
int get_int_val(const char *str);
|
||||
|
||||
#endif // UTILS_INCLUDED
|
83
client/mysqltest/warning.h
Normal file
83
client/mysqltest/warning.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
#ifndef WARNING_INCLUDED
|
||||
#define WARNING_INCLUDED
|
||||
|
||||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License, version 2.0,
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is designed to work with certain software (including
|
||||
// but not limited to OpenSSL) that is licensed under separate terms,
|
||||
// as designated in a particular file or component or in included license
|
||||
// documentation. The authors of MySQL hereby grant you an additional
|
||||
// permission to link the program and your derivative works with the
|
||||
// separately licensed software that they have either included with
|
||||
// the program or referenced in the documentation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License, version 2.0, for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
/// @file
|
||||
///
|
||||
/// This file declares the Warning class.
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
/// Class representing a warning.
|
||||
///
|
||||
/// Contains following information
|
||||
/// * A flag representing whether to ignore a warning or not
|
||||
/// * A flag representing the scope of a warning
|
||||
/// * Warning name
|
||||
/// * Warning number
|
||||
class Warning {
|
||||
public:
|
||||
Warning(std::uint32_t warning_code, const char *warning_name, bool once) {
|
||||
this->m_ignore_warning = false;
|
||||
this->m_once_property = once;
|
||||
this->m_warning_code = warning_code;
|
||||
this->m_warning_name.assign(warning_name);
|
||||
}
|
||||
|
||||
/// Check if a warning is disabled/enabled for next statement only.
|
||||
///
|
||||
/// @retval True if the warning is disabled or enabled for next
|
||||
/// statement only, false otherwise.
|
||||
bool expired() { return m_once_property; }
|
||||
|
||||
/// Return ignore_warning flag value
|
||||
///
|
||||
/// @retval True if ignore_warning flag is set, false otherwise.
|
||||
bool ignore_warning() { return m_ignore_warning; }
|
||||
|
||||
/// Return a symbolic name representing a warning
|
||||
///
|
||||
/// @retval Symbolic name for a warning.
|
||||
const char *warning_name() { return m_warning_name.c_str(); }
|
||||
|
||||
/// Return a warning code
|
||||
///
|
||||
/// @retval Warning code
|
||||
std::uint32_t warning_code() { return m_warning_code; }
|
||||
|
||||
/// Set ignore_warning flag
|
||||
///
|
||||
/// @param value Boolean value for ignore_warning flag
|
||||
void set_ignore_warning(bool value) { m_ignore_warning = value; }
|
||||
|
||||
private:
|
||||
bool m_ignore_warning;
|
||||
bool m_once_property;
|
||||
std::string m_warning_name;
|
||||
std::uint32_t m_warning_code;
|
||||
};
|
||||
|
||||
#endif // WARNING_INCLUDED
|
202
client/path.cc
Normal file
202
client/path.cc
Normal file
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
Copyright (c) 2012, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "client/path.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "my_dir.h"
|
||||
#include "my_inttypes.h"
|
||||
#include "my_io.h"
|
||||
#include "my_sys.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
Path::Path() = default;
|
||||
|
||||
Path::Path(const std::string &s) { path(s); }
|
||||
|
||||
Path::Path(const Path &p) {
|
||||
m_filename = p.m_filename;
|
||||
m_path = p.m_path;
|
||||
}
|
||||
|
||||
bool Path::path_getcwd() {
|
||||
char path[FN_REFLEN];
|
||||
if (my_getwd(path, FN_REFLEN - 1, MYF(MY_WME))) return false;
|
||||
m_path.clear();
|
||||
m_path.append(path);
|
||||
trim();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Path::trim() {
|
||||
if (m_path.length() <= 1) return;
|
||||
std::string::iterator it = m_path.end();
|
||||
--it;
|
||||
|
||||
while ((*it) == FN_LIBCHAR && m_path.length() > 1) {
|
||||
m_path.erase(it--);
|
||||
}
|
||||
}
|
||||
|
||||
void Path::parent_directory(Path *out) {
|
||||
size_t idx = m_path.rfind(FN_DIRSEP);
|
||||
if (idx == std::string::npos) {
|
||||
out->path("");
|
||||
} else
|
||||
out->path(m_path.substr(0, idx));
|
||||
}
|
||||
|
||||
Path &Path::up() {
|
||||
size_t idx = m_path.rfind(FN_DIRSEP);
|
||||
if (idx == std::string::npos) {
|
||||
m_path.clear();
|
||||
} else
|
||||
m_path.assign(m_path.substr(0, idx));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Path &Path::append(const std::string &path) {
|
||||
if (m_path.length() > 1 && path[0] != FN_LIBCHAR) m_path.append(FN_DIRSEP);
|
||||
m_path.append(path);
|
||||
trim();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Path &Path::filename_append(const std::string &ext) {
|
||||
m_filename.append(ext);
|
||||
trim();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Path::path(const std::string &p) {
|
||||
m_path.clear();
|
||||
m_path.append(p);
|
||||
trim();
|
||||
}
|
||||
|
||||
void Path::filename(const std::string &f) { m_filename = f; }
|
||||
|
||||
void Path::path(const Path &p) { path(p.m_path); }
|
||||
|
||||
void Path::filename(const Path &p) { path(p.m_filename); }
|
||||
|
||||
bool Path::qpath(const std::string &qp) {
|
||||
size_t idx = qp.rfind(FN_DIRSEP);
|
||||
if (idx == std::string::npos) {
|
||||
m_filename = qp;
|
||||
m_path.clear();
|
||||
} else {
|
||||
filename(qp.substr(idx + 1, qp.size() - idx));
|
||||
path(qp.substr(0, idx));
|
||||
}
|
||||
if (is_qualified_path())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Path::normalize_path() {
|
||||
if (!m_path.length()) return false;
|
||||
|
||||
char real_path[FN_REFLEN];
|
||||
size_t real_path_len;
|
||||
|
||||
real_path_len = cleanup_dirname(real_path, m_path.c_str());
|
||||
if (real_path_len > FN_REFLEN) return false;
|
||||
|
||||
if (my_realpath(real_path, real_path, MYF(0))) return false;
|
||||
|
||||
m_path.clear();
|
||||
m_path.append(real_path);
|
||||
trim();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Path::is_qualified_path() { return m_filename.length() > 0; }
|
||||
|
||||
bool Path::exists() {
|
||||
if (!is_qualified_path()) {
|
||||
MY_DIR *dir = my_dir(m_path.c_str(), MY_WANT_STAT | MY_DONT_SORT);
|
||||
if (dir == nullptr) return false;
|
||||
my_dirend(dir);
|
||||
return true;
|
||||
} else {
|
||||
MY_STAT s;
|
||||
std::string qpath(m_path);
|
||||
qpath.append(FN_DIRSEP).append(m_filename);
|
||||
if (my_stat(qpath.c_str(), &s, MYF(0)) == nullptr) return false;
|
||||
if (!MY_S_ISREG(s.st_mode)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string Path::to_str() {
|
||||
std::string qpath(m_path);
|
||||
if (m_filename.length() != 0) {
|
||||
qpath.append(FN_DIRSEP);
|
||||
qpath.append(m_filename);
|
||||
}
|
||||
return qpath;
|
||||
}
|
||||
|
||||
bool Path::empty() {
|
||||
if (!exists()) return true;
|
||||
MY_DIR *dir;
|
||||
bool ret = false;
|
||||
if (!(dir = my_dir(m_path.c_str(), MY_WANT_STAT | MY_DONT_SORT)))
|
||||
ret = false;
|
||||
else {
|
||||
if (dir->number_off_files == 2) ret = true;
|
||||
}
|
||||
my_dirend(dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
void Path::get_homedir() {
|
||||
struct passwd *pwd;
|
||||
pwd = getpwuid(geteuid());
|
||||
if (pwd == nullptr) return;
|
||||
if (pwd->pw_dir != nullptr)
|
||||
path(pwd->pw_dir);
|
||||
else
|
||||
path("");
|
||||
}
|
||||
#endif
|
||||
|
||||
std::ostream &operator<<(std::ostream &op, const Path &p) {
|
||||
std::string qpath(p.m_path);
|
||||
if (p.m_filename.length() != 0) {
|
||||
qpath.append(FN_DIRSEP);
|
||||
qpath.append(p.m_filename);
|
||||
}
|
||||
return op << qpath;
|
||||
}
|
90
client/path.h
Normal file
90
client/path.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright (c) 2012, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef PATH_UTIL_INCLUDED
|
||||
#define PATH_UTIL_INCLUDED
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
A helper class for handling file paths. The class can handle the memory
|
||||
on its own or it can wrap an external string.
|
||||
@note This is a rather trivial wrapper which doesn't handle malformed paths
|
||||
or filenames very well.
|
||||
@see unittest/gunit/path-t.cc
|
||||
|
||||
*/
|
||||
class Path {
|
||||
public:
|
||||
Path();
|
||||
|
||||
Path(const std::string &s);
|
||||
|
||||
Path(const Path &p);
|
||||
|
||||
bool path_getcwd();
|
||||
|
||||
void trim();
|
||||
|
||||
void parent_directory(Path *out);
|
||||
|
||||
Path &up();
|
||||
|
||||
Path &append(const std::string &path);
|
||||
|
||||
Path &filename_append(const std::string &ext);
|
||||
|
||||
void path(const std::string &p);
|
||||
|
||||
void filename(const std::string &f);
|
||||
|
||||
void path(const Path &p);
|
||||
|
||||
void filename(const Path &p);
|
||||
|
||||
bool qpath(const std::string &qp);
|
||||
|
||||
bool normalize_path();
|
||||
|
||||
bool is_qualified_path();
|
||||
|
||||
bool exists();
|
||||
|
||||
const std::string to_str();
|
||||
|
||||
bool empty();
|
||||
#ifndef _WIN32
|
||||
void get_homedir();
|
||||
#endif
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &op, const Path &p);
|
||||
|
||||
private:
|
||||
std::string m_path;
|
||||
std::string m_filename;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &op, const Path &p);
|
||||
|
||||
#endif
|
98
client/pattern_matcher.cc
Normal file
98
client/pattern_matcher.cc
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Copyright (c) 2017, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "pattern_matcher.h"
|
||||
|
||||
#include "my_dbug.h"
|
||||
#include "my_sys.h"
|
||||
|
||||
struct CHARSET_INFO;
|
||||
|
||||
/**
|
||||
@brief Parses concatenated patterns and adds them to internal pattern list
|
||||
|
||||
@param[in] patterns concatenated patterns
|
||||
@param[in] delimiter delimiter for pattern concatenation
|
||||
|
||||
@return number of added patterns
|
||||
*/
|
||||
size_t Pattern_matcher::add_patterns(const std::string &patterns,
|
||||
char delimiter) {
|
||||
DBUG_TRACE;
|
||||
const size_t length = patterns.length();
|
||||
size_t pattern_count = 0;
|
||||
|
||||
// we don't parse empty patterns
|
||||
if (length == 0) return pattern_count;
|
||||
|
||||
size_t first = 0;
|
||||
size_t last = 0;
|
||||
do {
|
||||
// find end of the token
|
||||
if ((last = patterns.find(delimiter, first)) == std::string::npos)
|
||||
last = length;
|
||||
|
||||
// we store only tokens that are not empty
|
||||
if (last - first > 0) {
|
||||
m_patterns.emplace(patterns, first, last - first);
|
||||
++pattern_count;
|
||||
}
|
||||
|
||||
first = last + 1;
|
||||
} while (last != length);
|
||||
|
||||
return pattern_count;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Verifies whether text matches any of the matcher internal patterns
|
||||
|
||||
@param[in] text string to search for patterns
|
||||
@param[in] info charset information for comparison rules
|
||||
|
||||
@return result of matching the text to internal patterns
|
||||
@retval true at least one pattern matches provided string
|
||||
@retval false string does not match any of the patterns
|
||||
*/
|
||||
bool Pattern_matcher::is_matching(const std::string &text,
|
||||
const CHARSET_INFO *info) const {
|
||||
DBUG_TRACE;
|
||||
|
||||
// traverse all patterns, return true on first match
|
||||
for (auto &pattern : m_patterns) {
|
||||
if (info->coll->wildcmp(info, text.c_str(), text.c_str() + text.length(),
|
||||
pattern.c_str(), pattern.c_str() + pattern.length(),
|
||||
WILD_ESCAPE, WILD_ONE, WILD_MANY) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// none of the patterns matched
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Removes all previously stored patterns from pattern matcher
|
||||
*/
|
||||
void Pattern_matcher::clear() { m_patterns.clear(); }
|
55
client/pattern_matcher.h
Normal file
55
client/pattern_matcher.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright (c) 2017, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "mysql/strings/m_ctype.h"
|
||||
|
||||
/**
|
||||
Enables comparison of strings against particular set of patterns. Patterns
|
||||
may contain wildcards (WILD_ONE/WILD_MANY/WILD_ESCAPE). Pattern strings may
|
||||
be added to the class through a special method. Matching method traverses all
|
||||
of the patterns within pattern matcher in search for a match.
|
||||
*/
|
||||
class Pattern_matcher {
|
||||
public:
|
||||
size_t add_patterns(const std::string &patterns, char delimiter = ':');
|
||||
bool is_matching(const std::string &text, const CHARSET_INFO *info) const;
|
||||
void clear();
|
||||
|
||||
private:
|
||||
/** any (single) character wild card */
|
||||
const static char WILD_ONE = '?';
|
||||
|
||||
/** zero or many characters wild card */
|
||||
const static char WILD_MANY = '*';
|
||||
|
||||
/** escape sequence character */
|
||||
const static char WILD_ESCAPE = '\\';
|
||||
|
||||
/** used for storing matcher patterns */
|
||||
std::unordered_set<std::string> m_patterns;
|
||||
};
|
261
client/readline.cc
Normal file
261
client/readline.cc
Normal file
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2.0,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is designed to work with certain software (including
|
||||
but not limited to OpenSSL) that is licensed under separate terms,
|
||||
as designated in a particular file or component or in included license
|
||||
documentation. The authors of MySQL hereby grant you an additional
|
||||
permission to link the program and your derivative works with the
|
||||
separately licensed software that they have either included with
|
||||
the program or referenced in the documentation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License, version 2.0, for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* readline for batch mode */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "client/my_readline.h"
|
||||
#include "m_string.h"
|
||||
#include "my_dbug.h"
|
||||
#include "my_dir.h"
|
||||
#include "my_inttypes.h"
|
||||
#include "my_io.h"
|
||||
#include "my_sys.h"
|
||||
#include "my_thread_local.h"
|
||||
#include "mysql/service_mysql_alloc.h"
|
||||
|
||||
static bool init_line_buffer(LINE_BUFFER *buffer, File file, ulong size,
|
||||
ulong max_size);
|
||||
static bool init_line_buffer_from_string(LINE_BUFFER *buffer, char *str);
|
||||
static size_t fill_buffer(LINE_BUFFER *buffer);
|
||||
static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length);
|
||||
|
||||
LINE_BUFFER *batch_readline_init(ulong max_size, FILE *file) {
|
||||
LINE_BUFFER *line_buff;
|
||||
|
||||
#ifndef _WIN32
|
||||
MY_STAT input_file_stat;
|
||||
if (my_fstat(fileno(file), &input_file_stat) ||
|
||||
MY_S_ISDIR(input_file_stat.st_mode) ||
|
||||
MY_S_ISBLK(input_file_stat.st_mode))
|
||||
return nullptr;
|
||||
#endif
|
||||
|
||||
if (!(line_buff =
|
||||
(LINE_BUFFER *)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(*line_buff),
|
||||
MYF(MY_WME | MY_ZEROFILL))))
|
||||
return nullptr;
|
||||
if (init_line_buffer(line_buff, my_fileno(file), batch_io_size, max_size)) {
|
||||
my_free(line_buff);
|
||||
return nullptr;
|
||||
}
|
||||
return line_buff;
|
||||
}
|
||||
|
||||
char *batch_readline(LINE_BUFFER *line_buff,
|
||||
bool binary_mode [[maybe_unused]]) {
|
||||
char *pos;
|
||||
ulong out_length;
|
||||
|
||||
if (!(pos = intern_read_line(line_buff, &out_length))) return nullptr;
|
||||
if (out_length && pos[out_length - 1] == '\n') {
|
||||
#if defined(_WIN32)
|
||||
/*
|
||||
On Windows platforms we also need to remove '\r',
|
||||
unconditionally.
|
||||
*/
|
||||
|
||||
/* Remove '\n' */
|
||||
if (--out_length && pos[out_length - 1] == '\r') /* Remove '\r' */
|
||||
out_length--;
|
||||
#else
|
||||
/*
|
||||
On Unix-like platforms we only remove it if we are not
|
||||
on binary mode.
|
||||
*/
|
||||
|
||||
/* Remove '\n' */
|
||||
if (--out_length && !binary_mode && pos[out_length - 1] == '\r')
|
||||
/* Remove '\r' */
|
||||
out_length--;
|
||||
#endif
|
||||
}
|
||||
line_buff->read_length = out_length;
|
||||
pos[out_length] = 0;
|
||||
DBUG_DUMP("Query: ", (unsigned char *)pos, out_length);
|
||||
return pos;
|
||||
}
|
||||
|
||||
void batch_readline_end(LINE_BUFFER *line_buff) {
|
||||
if (line_buff) {
|
||||
my_free(line_buff->buffer);
|
||||
my_free(line_buff);
|
||||
}
|
||||
}
|
||||
|
||||
LINE_BUFFER *batch_readline_command(LINE_BUFFER *line_buff, char *str) {
|
||||
if (!line_buff)
|
||||
if (!(line_buff =
|
||||
(LINE_BUFFER *)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(*line_buff),
|
||||
MYF(MY_WME | MY_ZEROFILL))))
|
||||
return nullptr;
|
||||
if (init_line_buffer_from_string(line_buff, str)) {
|
||||
my_free(line_buff);
|
||||
return nullptr;
|
||||
}
|
||||
return line_buff;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Functions to handle buffered readings of lines from a stream
|
||||
******************************************************************************/
|
||||
|
||||
static bool init_line_buffer(LINE_BUFFER *buffer, File file, ulong size,
|
||||
ulong max_buffer) {
|
||||
buffer->file = file;
|
||||
buffer->bufread = size;
|
||||
buffer->max_size = max_buffer;
|
||||
if (!(buffer->buffer = (char *)my_malloc(
|
||||
PSI_NOT_INSTRUMENTED, buffer->bufread + 1, MYF(MY_WME | MY_FAE))))
|
||||
return true;
|
||||
buffer->end_of_line = buffer->end = buffer->buffer;
|
||||
buffer->buffer[0] = 0; /* For easy start test */
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
init_line_buffer_from_string can be called on the same buffer
|
||||
several times. the resulting buffer will contain a
|
||||
concatenation of all strings separated by spaces
|
||||
*/
|
||||
static bool init_line_buffer_from_string(LINE_BUFFER *buffer, char *str) {
|
||||
const uint old_length = (uint)(buffer->end - buffer->buffer);
|
||||
const uint length = (uint)strlen(str);
|
||||
if (!(buffer->buffer = buffer->start_of_line = buffer->end_of_line =
|
||||
(char *)my_realloc(PSI_NOT_INSTRUMENTED, (uchar *)buffer->buffer,
|
||||
old_length + length + 2,
|
||||
MYF(MY_FAE | MY_ALLOW_ZERO_PTR))))
|
||||
return true;
|
||||
buffer->end = buffer->buffer + old_length;
|
||||
if (old_length) buffer->end[-1] = ' ';
|
||||
memcpy(buffer->end, str, length);
|
||||
buffer->end[length] = '\n';
|
||||
buffer->end[length + 1] = 0;
|
||||
buffer->end += length + 1;
|
||||
buffer->eof = 1;
|
||||
buffer->max_size = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Fill the buffer retaining the last n bytes at the beginning of the
|
||||
newly filled buffer (for backward context). Returns the number of new
|
||||
bytes read from disk.
|
||||
*/
|
||||
|
||||
static size_t fill_buffer(LINE_BUFFER *buffer) {
|
||||
size_t read_count;
|
||||
const uint bufbytes = (uint)(buffer->end - buffer->start_of_line);
|
||||
|
||||
if (buffer->eof) return 0; /* Everything read */
|
||||
|
||||
/* See if we need to grow the buffer. */
|
||||
|
||||
for (;;) {
|
||||
const uint start_offset = (uint)(buffer->start_of_line - buffer->buffer);
|
||||
read_count = (buffer->bufread - bufbytes) / batch_io_size;
|
||||
if ((read_count *= batch_io_size)) break;
|
||||
if (buffer->bufread * 2 > buffer->max_size) {
|
||||
/*
|
||||
So we must grow the buffer but we cannot due to the max_size limit.
|
||||
Return 0 w/o setting buffer->eof to signal this condition.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
buffer->bufread *= 2;
|
||||
if (!(buffer->buffer =
|
||||
(char *)my_realloc(PSI_NOT_INSTRUMENTED, buffer->buffer,
|
||||
buffer->bufread + 1, MYF(MY_WME | MY_FAE)))) {
|
||||
buffer->error = my_errno();
|
||||
return (size_t)-1;
|
||||
}
|
||||
buffer->start_of_line = buffer->buffer + start_offset;
|
||||
buffer->end = buffer->buffer + bufbytes;
|
||||
}
|
||||
|
||||
/* Shift stuff down. */
|
||||
if (buffer->start_of_line != buffer->buffer) {
|
||||
memmove(buffer->buffer, buffer->start_of_line, bufbytes);
|
||||
buffer->end = buffer->buffer + bufbytes;
|
||||
}
|
||||
|
||||
/* Read in new stuff. */
|
||||
if ((read_count = my_read(buffer->file, (uchar *)buffer->end, read_count,
|
||||
MYF(MY_WME))) == MY_FILE_ERROR) {
|
||||
buffer->error = my_errno();
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
DBUG_PRINT("fill_buff", ("Got %lu bytes", (ulong)read_count));
|
||||
|
||||
if (!read_count) {
|
||||
buffer->eof = 1;
|
||||
/* Kludge to pretend every nonempty file ends with a newline. */
|
||||
if (bufbytes && buffer->end[-1] != '\n') {
|
||||
read_count = 1;
|
||||
*buffer->end = '\n';
|
||||
}
|
||||
}
|
||||
buffer->end_of_line = (buffer->start_of_line = buffer->buffer) + bufbytes;
|
||||
buffer->end += read_count;
|
||||
*buffer->end = 0; /* Sentinel */
|
||||
return read_count;
|
||||
}
|
||||
|
||||
char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length) {
|
||||
char *pos;
|
||||
size_t length;
|
||||
DBUG_TRACE;
|
||||
|
||||
buffer->start_of_line = buffer->end_of_line;
|
||||
for (;;) {
|
||||
pos = buffer->end_of_line;
|
||||
while (*pos != '\n' && pos != buffer->end) pos++;
|
||||
if (pos == buffer->end) {
|
||||
/*
|
||||
fill_buffer() can return NULL on EOF (in which case we abort),
|
||||
on error, or when the internal buffer has hit the size limit.
|
||||
In the latter case return what we have read so far and signal
|
||||
string truncation.
|
||||
*/
|
||||
if (!(length = fill_buffer(buffer))) {
|
||||
if (buffer->eof) return nullptr;
|
||||
} else if (length == (size_t)-1)
|
||||
return nullptr;
|
||||
else
|
||||
continue;
|
||||
pos--; /* break line here */
|
||||
buffer->truncated = true;
|
||||
} else
|
||||
buffer->truncated = false;
|
||||
buffer->end_of_line = pos + 1;
|
||||
*out_length = (ulong)(pos + 1 - buffer->eof - buffer->start_of_line);
|
||||
|
||||
DBUG_DUMP("Query: ", (unsigned char *)buffer->start_of_line, *out_length);
|
||||
return buffer->start_of_line;
|
||||
}
|
||||
}
|
114
cmake/abi_check.cmake
Normal file
114
cmake/abi_check.cmake
Normal file
|
@ -0,0 +1,114 @@
|
|||
# Copyright (c) 2009, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
#
|
||||
# Headers which need to be checked for abi/api compatibility are in
|
||||
# API_PREPROCESSOR_HEADER. plugin.h is tested implicitly via
|
||||
# plugin_audit.h and plugin_ftparser.h.
|
||||
#
|
||||
# We use gcc specific preprocessing command and sed/diff, so it will
|
||||
# only be run on Unix and only if gcc is used. On some Unixes,
|
||||
# (Solaris) sed or diff might act differently from GNU, so we run only
|
||||
# on systems we can trust.
|
||||
# On Windows we use the Windows subsystem for Linux and gcc and sed
|
||||
# installed in it, if available.
|
||||
SET(RUN_ABI_CHECK 0)
|
||||
IF(LINUX AND MY_COMPILER_IS_GNU)
|
||||
SET(RUN_ABI_CHECK 1)
|
||||
ELSEIF(WIN32)
|
||||
FIND_PROGRAM(WSL_EXECUTABLE wsl HINTS C:/Windows/Sysnative)
|
||||
IF (WSL_EXECUTABLE)
|
||||
SET (COMPILER "gcc")
|
||||
# Check that the compiler is available under WSL.
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND ${WSL_EXECUTABLE} which ${COMPILER}
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE COMPILER_LOCATION)
|
||||
IF (COMPILER_LOCATION STREQUAL "/usr/bin/gcc")
|
||||
SET(RUN_ABI_CHECK 1)
|
||||
MESSAGE(STATUS "Will do ABI check using ${WSL_EXECUTABLE} (gcc/sed)")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
SET(API_PREPROCESSOR_HEADER
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/plugin_audit.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/plugin_ftparser.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/client_plugin.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/plugin_auth.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/plugin_keyring.h
|
||||
)
|
||||
IF(NOT WITHOUT_SERVER)
|
||||
LIST(APPEND API_PREPROCESSOR_HEADER
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_thread_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_mutex_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_rwlock_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_cond_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_file_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_socket_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_table_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_mdl_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_idle_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_stage_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_statement_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_transaction_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_memory_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_error_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_system_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_metric_v1.h
|
||||
${CMAKE_SOURCE_DIR}/include/mysql/services.h
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(MY_COMPILER_IS_GNU)
|
||||
IF(CMAKE_C_COMPILER MATCHES "ccache$")
|
||||
SET(COMPILER ${CMAKE_C_COMPILER_ARG1})
|
||||
STRING(REGEX REPLACE "^ " "" COMPILER ${COMPILER})
|
||||
ELSE()
|
||||
SET(COMPILER ${CMAKE_C_COMPILER})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(RUN_ABI_CHECK)
|
||||
UNSET(API_PP_FILES)
|
||||
FOREACH(file ${API_PREPROCESSOR_HEADER})
|
||||
LIST(APPEND API_PP_FILES ${file}.pp)
|
||||
ENDFOREACH()
|
||||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/abi_check.out
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCOMPILER=${COMPILER}
|
||||
-DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||
-DBINARY_DIR=${CMAKE_BINARY_DIR}
|
||||
-DWSL_EXECUTABLE=${WSL_EXECUTABLE}
|
||||
"-DABI_HEADERS=${API_PREPROCESSOR_HEADER}"
|
||||
-P ${CMAKE_SOURCE_DIR}/cmake/do_abi_check.cmake
|
||||
DEPENDS ${API_PREPROCESSOR_HEADER} ${API_PP_FILES}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
ADD_CUSTOM_TARGET(abi_check ALL
|
||||
DEPENDS ${CMAKE_BINARY_DIR}/abi_check.out
|
||||
)
|
||||
ENDIF()
|
64
cmake/add_custom_target.cmake
Normal file
64
cmake/add_custom_target.cmake
Normal file
|
@ -0,0 +1,64 @@
|
|||
# Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Wrap ADD_CUSTOM_TARGET to get rid of Warning MSB8065: File not created
|
||||
# Custom build for ... succeeded, but specified output ... has not been created.
|
||||
#
|
||||
# For the Visual Studio Generator, we generate an extra
|
||||
# 'cmake -E touch cmakefiles/${target_name}'
|
||||
#
|
||||
# Note that we handle only *one* COMMAND.
|
||||
# This is good enough for the current codebase.
|
||||
FUNCTION(MY_ADD_CUSTOM_TARGET TARGET_NAME)
|
||||
CMAKE_PARSE_ARGUMENTS(CUSTOM_ARG
|
||||
"ALL"
|
||||
"COMMENT;WORKING_DIRECTORY"
|
||||
"COMMAND;DEPENDS"
|
||||
${ARGN}
|
||||
)
|
||||
SET(TARGET_COMMAND)
|
||||
IF(CUSTOM_ARG_ALL)
|
||||
LIST(APPEND TARGET_COMMAND "ALL")
|
||||
ENDIF()
|
||||
IF(CUSTOM_ARG_DEPENDS)
|
||||
LIST(APPEND TARGET_COMMAND "DEPENDS" ${CUSTOM_ARG_DEPENDS})
|
||||
ENDIF()
|
||||
IF(CUSTOM_ARG_COMMAND)
|
||||
LIST(APPEND TARGET_COMMAND "COMMAND" ${CUSTOM_ARG_COMMAND})
|
||||
ENDIF()
|
||||
IF(CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||
STRING(TOLOWER "${TARGET_NAME}" target_name)
|
||||
LIST(APPEND TARGET_COMMAND
|
||||
"COMMAND" "${CMAKE_COMMAND}" -E touch cmakefiles/${target_name})
|
||||
ENDIF()
|
||||
IF(CUSTOM_ARG_COMMENT)
|
||||
LIST(APPEND TARGET_COMMAND "COMMENT" ${CUSTOM_ARG_COMMENT})
|
||||
ENDIF()
|
||||
IF(CUSTOM_ARG_WORKING_DIRECTORY)
|
||||
LIST(APPEND
|
||||
TARGET_COMMAND "WORKING_DIRECTORY" ${CUSTOM_ARG_WORKING_DIRECTORY})
|
||||
ENDIF()
|
||||
|
||||
ADD_CUSTOM_TARGET(${TARGET_NAME} ${TARGET_COMMAND})
|
||||
|
||||
ENDFUNCTION(MY_ADD_CUSTOM_TARGET)
|
148
cmake/bison.cmake
Normal file
148
cmake/bison.cmake
Normal file
|
@ -0,0 +1,148 @@
|
|||
# Copyright (c) 2009, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# This should be REQUIRED, but we have to support source tarball build.
|
||||
# https://dev.mysql.com/doc/refman/8.0/en/source-installation.html
|
||||
|
||||
SET(MIN_BISON_VERSION_REQUIRED "3.0.4")
|
||||
|
||||
# Bison seems to be stuck at version 2.3 in macOS.
|
||||
# Look for alternative custom installations, e.g.
|
||||
# /opt/bison-3.8.2/bin
|
||||
IF(APPLE AND NOT DEFINED BISON_EXECUTABLE)
|
||||
SET(OPT_BISON_DIR "/opt")
|
||||
IF(IS_DIRECTORY "${OPT_BISON_DIR}")
|
||||
SET(PREFERRED_BISON_VERSION "3.8.2")
|
||||
FILE(GLOB FOUND_BISON_BIN_DIRS
|
||||
LIST_DIRECTORIES true
|
||||
"${OPT_BISON_DIR}/bison-*/bin"
|
||||
)
|
||||
IF(FOUND_BISON_BIN_DIRS)
|
||||
# FILE GLOB seems to sort entries, but we need to REVERSE the list:
|
||||
# NATURAL uses strverscmp(3)
|
||||
LIST(SORT FOUND_BISON_BIN_DIRS COMPARE NATURAL ORDER DESCENDING)
|
||||
IF(IS_DIRECTORY "${OPT_BISON_DIR}/bison-${PREFERRED_BISON_VERSION}/bin")
|
||||
SET(BISON_PATHS "${OPT_BISON_DIR}/bison-${PREFERRED_BISON_VERSION}/bin")
|
||||
LIST(REMOVE_ITEM FOUND_BISON_BIN_DIRS "${BISON_PATHS}")
|
||||
ENDIF()
|
||||
FOREACH(path ${FOUND_BISON_BIN_DIRS})
|
||||
LIST(APPEND BISON_PATHS ${path})
|
||||
ENDFOREACH()
|
||||
MESSAGE(STATUS "Looking for bison in ${BISON_PATHS}")
|
||||
FIND_PROGRAM(BISON_EXECUTABLE bison
|
||||
NO_DEFAULT_PATH
|
||||
PATHS ${BISON_PATHS})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Look for HOMEBREW bison before the standard OS version.
|
||||
# Note that it is *not* symlinked like most other executables.
|
||||
# /usr/local/opt/bison/bin/bison
|
||||
# /usr/local/opt/bison -> ../Cellar/bison/3.8.2
|
||||
# /opt/homebrew/opt/bison
|
||||
IF(APPLE AND NOT DEFINED BISON_EXECUTABLE)
|
||||
FIND_PROGRAM(BREW_EXECUTABLE brew)
|
||||
IF(BREW_EXECUTABLE)
|
||||
EXECUTE_PROCESS(COMMAND ${BREW_EXECUTABLE} --prefix bison
|
||||
OUTPUT_VARIABLE BREW_BISON_PREFIX_OUTPUT
|
||||
RESULT_VARIABLE BREW_BISON_PREFIX_RESULT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
IF(BREW_BISON_PREFIX_RESULT EQUAL 0)
|
||||
SET(BISON_HOMEBREW_PATH "${BREW_BISON_PREFIX_OUTPUT}/bin")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
FIND_PROGRAM(BISON_EXECUTABLE bison
|
||||
NO_DEFAULT_PATH
|
||||
PATHS "${BISON_HOMEBREW_PATH}" "${HOMEBREW_HOME}/bison/bin")
|
||||
ENDIF()
|
||||
|
||||
# Look for winflexbison3, see e.g.
|
||||
# https://github.com/lexxmark/winflexbison/releases
|
||||
# or
|
||||
# https://chocolatey.org/install
|
||||
# choco install winflexbison3
|
||||
IF(WIN32 AND NOT DEFINED BISON_EXECUTABLE)
|
||||
SET(MY_BISON_PATHS
|
||||
c:/bin/bin
|
||||
c:/bin/lib/winflexbison3/tools
|
||||
c:/ProgramData/chocolatey/bin
|
||||
)
|
||||
FOREACH(_path ${MY_BISON_PATHS})
|
||||
FILE(TO_NATIVE_PATH ${_path} NATIVE_PATH)
|
||||
LIST(APPEND NATIVE_BISON_PATHS "${NATIVE_PATH}")
|
||||
ENDFOREACH()
|
||||
MESSAGE(STATUS "Looking for win_bison in ${NATIVE_BISON_PATHS}")
|
||||
FIND_PROGRAM(BISON_EXECUTABLE
|
||||
NAMES win_bison win-bison
|
||||
NO_DEFAULT_PATH
|
||||
PATHS ${NATIVE_BISON_PATHS}
|
||||
)
|
||||
# Look for Flex also, we may need it later.
|
||||
IF(BISON_EXECUTABLE)
|
||||
FIND_PROGRAM(FLEX_EXECUTABLE
|
||||
NAMES flex win-flex win_flex
|
||||
NO_DEFAULT_PATH
|
||||
PATHS ${NATIVE_BISON_PATHS}
|
||||
)
|
||||
FIND_PATH(FLEX_INCLUDE_DIR FlexLexer.h
|
||||
NO_DEFAULT_PATH
|
||||
PATHS ${NATIVE_BISON_PATHS}
|
||||
)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
FIND_PACKAGE(BISON)
|
||||
|
||||
IF(NOT BISON_FOUND)
|
||||
MESSAGE(WARNING "No bison found!!")
|
||||
MESSAGE(WARNING "If you have bison in a non-standard location, "
|
||||
"you can do 'cmake -DBISON_EXECUTABLE=</path/to/bison-executable>"
|
||||
)
|
||||
IF(APPLE)
|
||||
MESSAGE(WARNING "We recommend Homebrew bison.")
|
||||
ENDIF()
|
||||
RETURN()
|
||||
ENDIF()
|
||||
|
||||
IF(BISON_VERSION VERSION_LESS "${MIN_BISON_VERSION_REQUIRED}")
|
||||
MESSAGE(WARNING "Bison version ${BISON_VERSION} is old.")
|
||||
MESSAGE(WARNING "If you have a newer bison in a non-standard location, "
|
||||
"you can do 'cmake -DBISON_EXECUTABLE=</path/to/bison-executable>"
|
||||
)
|
||||
IF(APPLE)
|
||||
MESSAGE(WARNING "We recommend Homebrew bison.")
|
||||
ENDIF()
|
||||
MESSAGE(FATAL_ERROR
|
||||
"Please update to version ${MIN_BISON_VERSION_REQUIRED} or higher"
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
# TODO(tdidriks): replace with "--warnings=all"
|
||||
# Legacy backward compatibility suppressions:
|
||||
# * no-yacc: for --yacc
|
||||
# * no-precedence: for useless precedence or/and associativity rules
|
||||
SET(BISON_FLAGS_WARNINGS
|
||||
"--warnings=all,no-yacc,no-precedence"
|
||||
CACHE INTERNAL "BISON 3.x flags")
|
81
cmake/boost.cmake
Normal file
81
cmake/boost.cmake
Normal file
|
@ -0,0 +1,81 @@
|
|||
# Copyright (c) 2014, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
SET(BOOST_PACKAGE_NAME "boost_1_84_0")
|
||||
|
||||
# Always use the bundled version.
|
||||
SET(BOOST_SOURCE_DIR ${CMAKE_SOURCE_DIR}/extra/boost)
|
||||
|
||||
# Contains all header files we need.
|
||||
# (All the directories that contain at least one needed file).
|
||||
SET(BOOST_INCLUDE_DIR ${BOOST_SOURCE_DIR}/${BOOST_PACKAGE_NAME})
|
||||
|
||||
# We have a limited set of patches/bugfixes here:
|
||||
SET(BOOST_PATCHES_DIR
|
||||
"${CMAKE_SOURCE_DIR}/include/${BOOST_PACKAGE_NAME}/patches")
|
||||
|
||||
ADD_LIBRARY(boost INTERFACE)
|
||||
ADD_LIBRARY(extra::boost ALIAS boost)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(boost SYSTEM BEFORE INTERFACE
|
||||
${BOOST_PATCHES_DIR} ${BOOST_INCLUDE_DIR})
|
||||
|
||||
IF(NOT WIN32)
|
||||
# See boost/container_hash/hash.hpp
|
||||
# We pretend that the compiler is pre-c++98, in order to hide the
|
||||
# usage of std::unary_function<..> (which was removed in C++17)
|
||||
# For windows: see boost/config/stdlib/dinkumware.hpp
|
||||
TARGET_COMPILE_DEFINITIONS(boost INTERFACE BOOST_NO_CXX98_FUNCTION_BASE)
|
||||
ENDIF()
|
||||
|
||||
MESSAGE(STATUS "BOOST_PATCHES_DIR ${BOOST_PATCHES_DIR}")
|
||||
MESSAGE(STATUS "BOOST_INCLUDE_DIR ${BOOST_INCLUDE_DIR}")
|
||||
|
||||
IF(NOT WIN32)
|
||||
FILE(GLOB_RECURSE BOOST_PATCHES_LIST
|
||||
RELATIVE ${BOOST_PATCHES_DIR}
|
||||
${BOOST_PATCHES_DIR}/*.hpp
|
||||
)
|
||||
|
||||
SET(DIFF_COMMAND_LIST "#! /bin/bash")
|
||||
FOREACH(PATCHED_FILE ${BOOST_PATCHES_LIST})
|
||||
SET(ORIGINAL_FILE_PATH "${BOOST_INCLUDE_DIR}/${PATCHED_FILE}")
|
||||
SET(PATCHED_FILE_PATH "${BOOST_PATCHES_DIR}/${PATCHED_FILE}")
|
||||
LIST(APPEND DIFF_COMMAND_LIST
|
||||
"diff -u ${ORIGINAL_FILE_PATH} ${PATCHED_FILE_PATH}")
|
||||
ENDFOREACH()
|
||||
# Add true, to get zero exit status.
|
||||
LIST(APPEND DIFF_COMMAND_LIST "true")
|
||||
|
||||
STRING(REPLACE ";" "\n" DIFF_COMMAND_LINES "${DIFF_COMMAND_LIST}")
|
||||
|
||||
FILE(GENERATE
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/boost_patch_diffs
|
||||
CONTENT "${DIFF_COMMAND_LINES}"
|
||||
)
|
||||
|
||||
ADD_CUSTOM_TARGET(show_boost_patches
|
||||
COMMAND bash ${CMAKE_BINARY_DIR}/boost_patch_diffs
|
||||
DEPENDS ${CMAKE_BINARY_DIR}/boost_patch_diffs
|
||||
)
|
||||
ENDIF()
|
88
cmake/build_configurations/compiler_options.cmake
Normal file
88
cmake/build_configurations/compiler_options.cmake
Normal file
|
@ -0,0 +1,88 @@
|
|||
# Copyright (c) 2012, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
INCLUDE(CheckCCompilerFlag)
|
||||
INCLUDE(CheckCXXCompilerFlag)
|
||||
INCLUDE(cmake/floating_point.cmake)
|
||||
|
||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
# Compiler options
|
||||
IF(UNIX)
|
||||
|
||||
IF(MY_COMPILER_IS_GNU_OR_CLANG AND NOT SOLARIS)
|
||||
SET(SECTIONS_FLAG "-ffunction-sections -fdata-sections")
|
||||
ELSE()
|
||||
SET(SECTIONS_FLAG)
|
||||
ENDIF()
|
||||
|
||||
# Default GCC flags
|
||||
IF(MY_COMPILER_IS_GNU)
|
||||
SET(COMMON_C_FLAGS "-fno-omit-frame-pointer")
|
||||
# Disable inline optimizations for valgrind testing to avoid false positives
|
||||
IF(WITH_VALGRIND)
|
||||
STRING_PREPEND(COMMON_C_FLAGS "-fno-inline ")
|
||||
ENDIF()
|
||||
# Disable floating point expression contractions to avoid result differences
|
||||
IF(HAVE_C_FLOATING_POINT_FUSED_MADD)
|
||||
STRING_APPEND(COMMON_C_FLAGS " -ffp-contract=off")
|
||||
ENDIF()
|
||||
|
||||
SET(COMMON_CXX_FLAGS "-std=c++20 -fno-omit-frame-pointer")
|
||||
# Disable inline optimizations for valgrind testing to avoid false positives
|
||||
IF(WITH_VALGRIND)
|
||||
STRING_PREPEND(COMMON_CXX_FLAGS "-fno-inline ")
|
||||
ENDIF()
|
||||
# Disable floating point expression contractions to avoid result differences
|
||||
IF(HAVE_CXX_FLOATING_POINT_FUSED_MADD)
|
||||
STRING_APPEND(COMMON_CXX_FLAGS " -ffp-contract=off")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Default Clang flags
|
||||
IF(MY_COMPILER_IS_CLANG)
|
||||
SET(COMMON_C_FLAGS "-fno-omit-frame-pointer")
|
||||
SET(COMMON_CXX_FLAGS "-std=c++20 -fno-omit-frame-pointer")
|
||||
ENDIF()
|
||||
|
||||
# Faster TLS model
|
||||
# libprotobuf-lite.so.24.4: cannot allocate memory in static TLS block
|
||||
IF(MY_COMPILER_IS_GNU_OR_CLANG
|
||||
AND NOT LINUX_ARM
|
||||
AND NOT SOLARIS AND NOT LINUX_RHEL6 AND NOT LINUX_ALPINE)
|
||||
STRING_APPEND(COMMON_C_FLAGS " -ftls-model=initial-exec")
|
||||
STRING_APPEND(COMMON_CXX_FLAGS " -ftls-model=initial-exec")
|
||||
ENDIF()
|
||||
|
||||
# Use STRING_PREPEND here, so command-line input can override our defaults.
|
||||
STRING_PREPEND(CMAKE_C_FLAGS "${COMMON_C_FLAGS} ")
|
||||
STRING_PREPEND(CMAKE_C_FLAGS_RELWITHDEBINFO "${SECTIONS_FLAG} ")
|
||||
STRING_PREPEND(CMAKE_C_FLAGS_RELEASE "${SECTIONS_FLAG} ")
|
||||
STRING_PREPEND(CMAKE_C_FLAGS_MINSIZEREL "${SECTIONS_FLAG} ")
|
||||
|
||||
STRING_PREPEND(CMAKE_CXX_FLAGS "${COMMON_CXX_FLAGS} ")
|
||||
STRING_PREPEND(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${SECTIONS_FLAG} ")
|
||||
STRING_PREPEND(CMAKE_CXX_FLAGS_RELEASE "${SECTIONS_FLAG} ")
|
||||
STRING_PREPEND(CMAKE_CXX_FLAGS_MINSIZEREL "${SECTIONS_FLAG} ")
|
||||
|
||||
ENDIF()
|
62
cmake/build_configurations/mysql_release.cmake
Normal file
62
cmake/build_configurations/mysql_release.cmake
Normal file
|
@ -0,0 +1,62 @@
|
|||
# Copyright (c) 2010, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# This file includes build settings used for MySQL release
|
||||
|
||||
INCLUDE(CheckIncludeFiles)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
|
||||
OPTION(DEBUG_EXTNAME "" ON)
|
||||
|
||||
IF(LINUX AND CMAKE_BUILD_TYPE)
|
||||
IF(CMAKE_BUILD_TYPE_UPPER MATCHES "REL")
|
||||
OPTION(REPRODUCIBLE_BUILD "" ON)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(NOT COMPILATION_COMMENT)
|
||||
SET(COMPILATION_COMMENT "MySQL Community (GPL)")
|
||||
ENDIF()
|
||||
|
||||
IF(NOT COMPILATION_COMMENT_SERVER)
|
||||
SET(COMPILATION_COMMENT_SERVER "MySQL Community Server (GPL)")
|
||||
ENDIF()
|
||||
|
||||
IF(LINUX)
|
||||
IF(NOT IGNORE_AIO_CHECK)
|
||||
# Ensure aio is available on Linux (required by InnoDB)
|
||||
CHECK_INCLUDE_FILES(libaio.h HAVE_LIBAIO_H)
|
||||
CHECK_LIBRARY_EXISTS(aio io_queue_init "" HAVE_LIBAIO)
|
||||
IF(NOT HAVE_LIBAIO_H OR NOT HAVE_LIBAIO)
|
||||
MESSAGE(FATAL_ERROR "
|
||||
aio is required on Linux, you need to install the required library:
|
||||
|
||||
Debian/Ubuntu: apt-get install libaio-dev
|
||||
RedHat/Fedora/Oracle Linux: yum install libaio-devel
|
||||
SuSE: zypper install libaio-devel
|
||||
|
||||
If you really do not want it, pass -DIGNORE_AIO_CHECK to cmake.
|
||||
")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
38
cmake/character_sets.cmake
Normal file
38
cmake/character_sets.cmake
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Copyright (c) 2009, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Charsets and collations
|
||||
IF(NOT DEFAULT_CHARSET)
|
||||
SET(DEFAULT_CHARSET "utf8mb4")
|
||||
ENDIF()
|
||||
|
||||
IF(NOT DEFAULT_COLLATION)
|
||||
SET(DEFAULT_COLLATION "utf8mb4_0900_ai_ci")
|
||||
ENDIF()
|
||||
|
||||
IF(WITH_EXTRA_CHARSETS AND NOT WITH_EXTRA_CHARSETS STREQUAL "all")
|
||||
MESSAGE(WARNING "Option WITH_EXTRA_CHARSETS is no longer supported")
|
||||
ENDIF()
|
||||
|
||||
SET(MYSQL_DEFAULT_CHARSET_NAME "${DEFAULT_CHARSET}")
|
||||
SET(MYSQL_DEFAULT_COLLATION_NAME "${DEFAULT_COLLATION}")
|
96
cmake/cmake_policies.cmake
Normal file
96
cmake/cmake_policies.cmake
Normal file
|
@ -0,0 +1,96 @@
|
|||
# Copyright (c) 2006, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Set various cmake policies. This must be done *after* CMAKE_MINIMUM_REQUIRED.
|
||||
|
||||
# Explicitly set CMP0018 and CMP0022 = NEW since newer versions of
|
||||
# CMake has OLD as default even if OLD is deprecated.
|
||||
# See cmake --help-policy CMP0018 / CMP0022
|
||||
CMAKE_POLICY(SET CMP0018 NEW)
|
||||
CMAKE_POLICY(SET CMP0022 NEW)
|
||||
|
||||
# Disallow use of the LOCATION property for build targets.
|
||||
CMAKE_POLICY(SET CMP0026 NEW)
|
||||
|
||||
# Include TARGET_OBJECTS expressions.
|
||||
CMAKE_POLICY(SET CMP0051 NEW)
|
||||
|
||||
# INTERPROCEDURAL_OPTIMIZATION is enforced when enabled (CMake 3.9+)
|
||||
IF(POLICY CMP0069)
|
||||
CMAKE_POLICY(SET CMP0069 NEW)
|
||||
ENDIF()
|
||||
|
||||
# Do not produce ``<tgt>_LIB_DEPENDS`` cache entries to propagate library
|
||||
# link dependencies. In cmake code, use this instead:
|
||||
# GET_TARGET_PROPERTY(TARGET_LIB_DEPENDS ${target} LINK_LIBRARIES)
|
||||
IF(POLICY CMP0073)
|
||||
CMAKE_POLICY(SET CMP0073 NEW)
|
||||
ENDIF()
|
||||
|
||||
# In CMake 3.12 and above, the
|
||||
#
|
||||
# * ``check_include_file`` macro in the ``CheckIncludeFile`` module, the
|
||||
# * ``check_include_file_cxx`` macro in the
|
||||
# ``CheckIncludeFileCXX`` module, and the
|
||||
# * ``check_include_files`` macro in the ``CheckIncludeFiles`` module
|
||||
#
|
||||
# now prefer to link the check executable to the libraries listed in the
|
||||
# ``CMAKE_REQUIRED_LIBRARIES`` variable.
|
||||
IF(POLICY CMP0075)
|
||||
CMAKE_POLICY(SET CMP0075 NEW)
|
||||
ENDIF()
|
||||
|
||||
# versionadded:: 3.15
|
||||
# In CMake 3.14 and below, MSVC runtime library selection flags are added to
|
||||
# the default ``CMAKE_<LANG>_FLAGS_<CONFIG>`` cache entries by CMake
|
||||
# automatically.
|
||||
#
|
||||
# .. note::
|
||||
#
|
||||
# Once the policy has taken effect at the top of a project, that choice
|
||||
# must be used throughout the tree. In projects that have nested projects
|
||||
# in subdirectories, be sure to convert everything together.
|
||||
#
|
||||
# https://cmake.org/cmake/help/latest/policy/CMP0091.html
|
||||
# This policy was introduced in CMake version 3.15. It may be set by
|
||||
# cmake_policy() or cmake_minimum_required(). If it is not set, CMake
|
||||
# does not warn, and uses OLD behavior.
|
||||
#
|
||||
# We have code in cmake/os/Windows.cmake to handle the OLD behaviour.
|
||||
# Whenever we add 3rd party stuff: be sure to keep the policy.
|
||||
# Also look for CMAKE_MSVC_RUNTIME_LIBRARY and MSVC_RUNTIME_LIBRARY
|
||||
# in 3rd party cmake code.
|
||||
IF(POLICY CMP0091)
|
||||
# Explicitly setting it to OLD will issue a warning for some cmake versions,
|
||||
# so just keep the default behaviour, see above.
|
||||
# CMAKE_POLICY(SET CMP0091 OLD)
|
||||
ENDIF()
|
||||
|
||||
# versionadded:: 3.18
|
||||
# It is not allowed to create an ``ALIAS`` target with the same name as an
|
||||
# another target.
|
||||
# The ``OLD`` behavior for this policy is to allow target overwrite.
|
||||
# The ``NEW`` behavior of this policy is to prevent target overwriting.
|
||||
IF(POLICY CMP0107)
|
||||
CMAKE_POLICY(SET CMP0107 NEW)
|
||||
ENDIF()
|
196
cmake/compile_flags.cmake
Normal file
196
cmake/compile_flags.cmake
Normal file
|
@ -0,0 +1,196 @@
|
|||
# Copyright (c) 2014, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
## ADD_COMPILE_FLAGS(<source files> COMPILE_FLAGS <flags>)
|
||||
## Use this for adding compiler flags to source files.
|
||||
FUNCTION(ADD_COMPILE_FLAGS)
|
||||
SET(FILES "")
|
||||
SET(FLAGS "")
|
||||
SET(COMPILE_FLAGS_SEEN)
|
||||
FOREACH(ARG ${ARGV})
|
||||
IF(ARG STREQUAL "COMPILE_FLAGS")
|
||||
SET(COMPILE_FLAGS_SEEN 1)
|
||||
ELSEIF(COMPILE_FLAGS_SEEN)
|
||||
LIST(APPEND FLAGS ${ARG})
|
||||
IF(${ARG} MATCHES "^-D")
|
||||
MESSAGE(WARNING
|
||||
"${ARG} should be in COMPILE_DEFINITIONS not COMPILE_FLAGS")
|
||||
ENDIF()
|
||||
ELSE()
|
||||
LIST(APPEND FILES ${ARG})
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
FOREACH(FILE ${FILES})
|
||||
FOREACH(FLAG ${FLAGS})
|
||||
GET_SOURCE_FILE_PROPERTY(PROP ${FILE} COMPILE_FLAGS)
|
||||
IF(NOT PROP)
|
||||
SET(PROP ${FLAG})
|
||||
ELSE()
|
||||
STRING_APPEND(PROP " ${FLAG}")
|
||||
ENDIF()
|
||||
SET_SOURCE_FILES_PROPERTIES(
|
||||
${FILE} PROPERTIES COMPILE_FLAGS "${PROP}"
|
||||
)
|
||||
ENDFOREACH()
|
||||
ENDFOREACH()
|
||||
ENDFUNCTION(ADD_COMPILE_FLAGS)
|
||||
|
||||
|
||||
## MY_ADD_COMPILE_DEFINITIONS(<source files> COMPILE_DEFINITIONS <flags>)
|
||||
## Use this for adding preprocessor flags VAR or VAR=value to source files.
|
||||
## cmake will prefix with '-D' and sort all COMPILE_DEFINITIONS alphabetically.
|
||||
FUNCTION(MY_ADD_COMPILE_DEFINITIONS)
|
||||
SET(FILES "")
|
||||
SET(FLAGS "")
|
||||
SET(COMPILE_DEFINITIONS_SEEN)
|
||||
FOREACH(ARG ${ARGV})
|
||||
IF(ARG STREQUAL "COMPILE_DEFINITIONS")
|
||||
SET(COMPILE_DEFINITIONS_SEEN 1)
|
||||
ELSEIF(COMPILE_DEFINITIONS_SEEN)
|
||||
LIST(APPEND FLAGS ${ARG})
|
||||
ELSE()
|
||||
LIST(APPEND FILES ${ARG})
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
FOREACH(FILE ${FILES})
|
||||
GET_SOURCE_FILE_PROPERTY(DEFS ${FILE} COMPILE_DEFINITIONS)
|
||||
IF(NOT DEFS)
|
||||
SET(DEFS ${FLAGS})
|
||||
ELSE()
|
||||
LIST(APPEND DEFS ${FLAGS})
|
||||
ENDIF()
|
||||
SET_SOURCE_FILES_PROPERTIES(
|
||||
${FILE} PROPERTIES COMPILE_DEFINITIONS "${DEFS}")
|
||||
ENDFOREACH()
|
||||
ENDFUNCTION(MY_ADD_COMPILE_DEFINITIONS)
|
||||
|
||||
# -flto[=n] or -flto=auto or -flto=jobserver
|
||||
SET(MY_COMPILER_FLAG_FLTO " -flto(=[0-9a-z]+)?")
|
||||
|
||||
# Remove compiler flag/pattern from CMAKE_C_FLAGS or CMAKE_CXX_FLAGS
|
||||
FUNCTION(REMOVE_CMAKE_COMPILER_FLAGS FLAG_VAR PATTERN)
|
||||
STRING(REGEX REPLACE "${PATTERN}" "" ${FLAG_VAR} "${${FLAG_VAR}}")
|
||||
SET(${FLAG_VAR} "${${FLAG_VAR}}" PARENT_SCOPE)
|
||||
ENDFUNCTION()
|
||||
|
||||
# Set CMAKE_C_FLAGS and CMAKE_CXX_FLAGS to 'rpm --eval %optflags'
|
||||
FUNCTION(ADD_LINUX_RPM_FLAGS)
|
||||
EXECUTE_PROCESS(COMMAND ${MY_RPM} --eval %optflags
|
||||
OUTPUT_VARIABLE RPM_EVAL_OPTFLAGS
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RPM_EVAL_RESULT
|
||||
)
|
||||
IF(RPM_EVAL_RESULT EQUAL 0)
|
||||
STRING_APPEND(CMAKE_C_FLAGS " ${RPM_EVAL_OPTFLAGS}")
|
||||
STRING_APPEND(CMAKE_CXX_FLAGS " ${RPM_EVAL_OPTFLAGS}")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
|
||||
ELSE()
|
||||
MESSAGE(FATAL_ERROR
|
||||
"WITH_PACKAGE_FLAGS=on but rpm --eval %optflags failed")
|
||||
ENDIF()
|
||||
ENDFUNCTION(ADD_LINUX_RPM_FLAGS)
|
||||
|
||||
# Set CMAKE_C_FLAGS and CMAKE_CXX_FLAGS to
|
||||
# dpkg-buildflags --get <lang>FLAGS CPPFLAGS
|
||||
# Set CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS and
|
||||
# CMAKE_SHARED_LINKER_FLAGS to
|
||||
# dpkg-buildflags --get LDFLAGS
|
||||
FUNCTION(ADD_LINUX_DEB_FLAGS)
|
||||
FOREACH(flag CPPFLAGS CFLAGS CXXFLAGS LDFLAGS)
|
||||
EXECUTE_PROCESS(COMMAND ${MY_DPKG_BUILDFLAGS} --get ${flag}
|
||||
OUTPUT_VARIABLE GET_${flag}
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE GET_RESULT
|
||||
)
|
||||
IF(NOT GET_RESULT EQUAL 0)
|
||||
MESSAGE(FATAL_ERROR
|
||||
"WITH_PACKAGE_FLAGS=on but dpkg-buildflags --get failed")
|
||||
ENDIF()
|
||||
SET(CMAKE_C_FLAGS "${GET_CFLAGS} ${GET_CPPFLAGS}" PARENT_SCOPE)
|
||||
SET(CMAKE_CXX_FLAGS "${GET_CXXFLAGS} ${GET_CPPFLAGS}" PARENT_SCOPE)
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${GET_LDFLAGS}" PARENT_SCOPE)
|
||||
SET(CMAKE_MODULE_LINKER_FLAGS "${GET_LDFLAGS}" PARENT_SCOPE)
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${GET_LDFLAGS}" PARENT_SCOPE)
|
||||
ENDFOREACH()
|
||||
ENDFUNCTION(ADD_LINUX_DEB_FLAGS)
|
||||
|
||||
# See if we can do "-fuse-ld=${LINKER}" for gcc/clang on Linux.
|
||||
# If compilation/linking succeeds, we extend misc cmake LINKER_FLAGS,
|
||||
# and set OUTPUT_RESULT to 1.
|
||||
FUNCTION(CHECK_ALTERNATIVE_LINKER LINKER OUTPUT_RESULT)
|
||||
SET(ACCEPTED_VERSION 1)
|
||||
CMAKE_PUSH_CHECK_STATE(RESET)
|
||||
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "-fuse-ld=${LINKER}")
|
||||
CHECK_C_SOURCE_COMPILES("int main() {}" C_LD_${LINKER}_RESULT)
|
||||
CHECK_CXX_SOURCE_COMPILES("int main() {}" CXX_LD_${LINKER}_RESULT)
|
||||
IF(C_LD_${LINKER}_RESULT AND CXX_LD_${LINKER}_RESULT)
|
||||
IF(${LINKER} STREQUAL "mold")
|
||||
FIND_PROGRAM(MOLD_EXECUTABLE "mold")
|
||||
IF(MOLD_EXECUTABLE)
|
||||
EXECUTE_PROCESS(COMMAND ${MOLD_EXECUTABLE} --version
|
||||
OUTPUT_VARIABLE MOLD_OUTPUT
|
||||
RESULT_VARIABLE MOLD_RESULT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
STRING(REGEX MATCH "^mold ([.0-9]+)" VERSION "${MOLD_OUTPUT}")
|
||||
IF(NOT CMAKE_MATCH_1 OR CMAKE_MATCH_1 VERSION_LESS "2.0.0")
|
||||
MESSAGE(STATUS
|
||||
"This version of mold has an incompatible version: ${MOLD_OUTPUT}")
|
||||
SET(ACCEPTED_VERSION 0)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(ACCEPTED_VERSION AND C_LD_${LINKER}_RESULT AND CXX_LD_${LINKER}_RESULT)
|
||||
FOREACH(flag
|
||||
CMAKE_EXE_LINKER_FLAGS
|
||||
CMAKE_MODULE_LINKER_FLAGS
|
||||
CMAKE_SHARED_LINKER_FLAGS
|
||||
)
|
||||
STRING_APPEND(${flag} " -fuse-ld=${LINKER}")
|
||||
SET(${flag} ${${flag}} PARENT_SCOPE)
|
||||
ENDFOREACH()
|
||||
SET(${OUTPUT_RESULT} 1 PARENT_SCOPE)
|
||||
ELSE()
|
||||
SET(${OUTPUT_RESULT} 0 PARENT_SCOPE)
|
||||
MESSAGE(STATUS "Cannot use ${LINKER} on this platform")
|
||||
ENDIF()
|
||||
|
||||
CMAKE_POP_CHECK_STATE()
|
||||
ENDFUNCTION(CHECK_ALTERNATIVE_LINKER)
|
||||
|
||||
FUNCTION(EXCLUDE_FROM_MSVC_PGO TARGET_LIB)
|
||||
# Exclude archive from PGO on Windows to avoid linker error LNK1248
|
||||
IF(MSVC AND ((FPROFILE_GENERATE OR FPROFILE_USE)))
|
||||
TARGET_COMPILE_OPTIONS(${TARGET_LIB} PRIVATE /GL-)
|
||||
ENDIF()
|
||||
ENDFUNCTION(EXCLUDE_FROM_MSVC_PGO)
|
||||
|
||||
FUNCTION(EXCLUDE_FILE_FROM_MSVC_PGO TARGET_FILE)
|
||||
# Exclude archive from PGO on Windows to avoid linker error LNK1248
|
||||
IF(MSVC AND ((FPROFILE_GENERATE OR FPROFILE_USE)))
|
||||
ADD_COMPILE_FLAGS(${TARGET_FILE} COMPILE_FLAGS /GL-)
|
||||
ENDIF()
|
||||
ENDFUNCTION(EXCLUDE_FILE_FROM_MSVC_PGO)
|
152
cmake/component.cmake
Normal file
152
cmake/component.cmake
Normal file
|
@ -0,0 +1,152 @@
|
|||
# Copyright (c) 2013, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# MYSQL_ADD_COMPONENT(component sources... options/keywords...)
|
||||
|
||||
MACRO(MYSQL_ADD_COMPONENT component_arg)
|
||||
SET(COMPONENT_OPTIONS
|
||||
MODULE_ONLY # generate dynamic library
|
||||
SKIP_INSTALL
|
||||
STATIC # generate new static library
|
||||
TEST_ONLY # include library only with test distribution
|
||||
)
|
||||
SET(COMPONENT_ONE_VALUE_KW
|
||||
)
|
||||
SET(COMPONENT_MULTI_VALUE_KW
|
||||
LINK_LIBRARIES # lib1 ... libN
|
||||
)
|
||||
|
||||
CMAKE_PARSE_ARGUMENTS(ARG
|
||||
"${COMPONENT_OPTIONS}"
|
||||
"${COMPONENT_ONE_VALUE_KW}"
|
||||
"${COMPONENT_MULTI_VALUE_KW}"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
SET(component ${component_arg})
|
||||
SET(SOURCES ${ARG_UNPARSED_ARGUMENTS})
|
||||
|
||||
STRING(TOUPPER ${component} component)
|
||||
STRING(TOLOWER ${component} component_lower)
|
||||
STRING(TOLOWER component_${component} target)
|
||||
|
||||
GET_PROPERTY(CWD_DEFINITIONS DIRECTORY PROPERTY COMPILE_DEFINITIONS)
|
||||
LIST(FIND CWD_DEFINITIONS "MYSQL_SERVER" FOUND_DEFINITION)
|
||||
IF(NOT FOUND_DEFINITION EQUAL -1)
|
||||
MESSAGE(FATAL_ERROR
|
||||
"component ${component} has -DMYSQL_SERVER")
|
||||
ENDIF()
|
||||
|
||||
# If not dynamic component, add it to list of built-ins
|
||||
IF (ARG_STATIC)
|
||||
IF (NOT "${component}" STREQUAL "MYSQL_SERVER")
|
||||
MESSAGE(FATAL_ERROR "Only one server built-in component is expected.")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Build either static library or module
|
||||
IF (ARG_STATIC)
|
||||
SET(kind STATIC)
|
||||
ELSEIF(ARG_MODULE_ONLY)
|
||||
SET(kind MODULE)
|
||||
ELSE()
|
||||
MESSAGE(FATAL_ERROR "Unknown component type ${target}")
|
||||
ENDIF()
|
||||
|
||||
ADD_VERSION_INFO(${kind} SOURCES "")
|
||||
ADD_LIBRARY(${target} ${kind} ${SOURCES})
|
||||
|
||||
TARGET_COMPILE_DEFINITIONS(${target} PUBLIC MYSQL_COMPONENT)
|
||||
IF(COMPRESS_DEBUG_SECTIONS)
|
||||
MY_TARGET_LINK_OPTIONS(${target}
|
||||
"LINKER:--compress-debug-sections=zlib")
|
||||
ENDIF()
|
||||
|
||||
IF(ARG_LINK_LIBRARIES)
|
||||
TARGET_LINK_LIBRARIES(${target} ${ARG_LINK_LIBRARIES})
|
||||
ENDIF()
|
||||
|
||||
SET_TARGET_PROPERTIES(${target} PROPERTIES PREFIX "")
|
||||
ADD_DEPENDENCIES(${target} GenError)
|
||||
|
||||
IF (ARG_MODULE_ONLY)
|
||||
SET_TARGET_PROPERTIES(${target} PROPERTIES OUTPUT_NAME "${target}")
|
||||
# Store all components in the same directory, for easier testing.
|
||||
SET_TARGET_PROPERTIES(${target} PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugin_output_directory
|
||||
)
|
||||
|
||||
# For APPLE: adjust path dependecy for SSL shared libraries.
|
||||
SET_PATH_TO_CUSTOM_SSL_FOR_APPLE(${target})
|
||||
|
||||
IF(APPLE)
|
||||
TARGET_LINK_OPTIONS(${target} PRIVATE LINKER:-no_warn_duplicate_libraries)
|
||||
ENDIF()
|
||||
|
||||
IF(WIN32_CLANG AND WITH_ASAN)
|
||||
TARGET_LINK_LIBRARIES(${target}
|
||||
"${ASAN_LIB_DIR}/clang_rt.asan_dll_thunk-x86_64.lib")
|
||||
ENDIF()
|
||||
|
||||
# To hide the component symbols in the shared object
|
||||
IF(UNIX)
|
||||
# Use this also for component libraries and tests.
|
||||
SET(COMPONENT_COMPILE_VISIBILITY
|
||||
"-fvisibility=hidden" CACHE INTERNAL
|
||||
"Use -fvisibility=hidden for components" FORCE)
|
||||
TARGET_COMPILE_OPTIONS(${target} PRIVATE "-fvisibility=hidden")
|
||||
ENDIF()
|
||||
|
||||
IF(NOT ARG_SKIP_INSTALL)
|
||||
# Install dynamic library.
|
||||
IF(ARG_TEST_ONLY)
|
||||
SET(INSTALL_COMPONENT Test)
|
||||
ELSE()
|
||||
SET(INSTALL_COMPONENT Server)
|
||||
ENDIF()
|
||||
|
||||
ADD_INSTALL_RPATH_FOR_OPENSSL(${target})
|
||||
MYSQL_INSTALL_TARGET(${target}
|
||||
DESTINATION ${INSTALL_PLUGINDIR}
|
||||
COMPONENT ${INSTALL_COMPONENT})
|
||||
INSTALL_DEBUG_TARGET(${target}
|
||||
DESTINATION ${INSTALL_PLUGINDIR}/debug
|
||||
COMPONENT ${INSTALL_COMPONENT})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
ADD_DEPENDENCIES(component_all ${target})
|
||||
|
||||
ENDMACRO(MYSQL_ADD_COMPONENT)
|
||||
|
||||
|
||||
# Add all CMake projects under components
|
||||
MACRO(CONFIGURE_COMPONENTS)
|
||||
FILE(GLOB dirs_components ${CMAKE_SOURCE_DIR}/components/*)
|
||||
FILE(GLOB dirs_components_test ${CMAKE_SOURCE_DIR}/components/test/*)
|
||||
FOREACH(dir ${dirs_components} ${dirs_components_test})
|
||||
IF (EXISTS ${dir}/CMakeLists.txt)
|
||||
ADD_SUBDIRECTORY(${dir})
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
ENDMACRO()
|
1
cmake/configurable_file_content.in
Normal file
1
cmake/configurable_file_content.in
Normal file
|
@ -0,0 +1 @@
|
|||
@CMAKE_CONFIGURABLE_FILE_CONTENT@
|
74
cmake/copy_custom_library.cmake
Normal file
74
cmake/copy_custom_library.cmake
Normal file
|
@ -0,0 +1,74 @@
|
|||
# Copyright (c) 2020, 2024, Oracle and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2.0,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is designed to work with certain software (including
|
||||
# but not limited to OpenSSL) that is licensed under separate terms,
|
||||
# as designated in a particular file or component or in included license
|
||||
# documentation. The authors of MySQL hereby grant you an additional
|
||||
# permission to link the program and your derivative works with the
|
||||
# separately licensed software that they have either included with
|
||||
# the program or referenced in the documentation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License, version 2.0, for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
IF(EXISTS "./${library_version}")
|
||||
RETURN()
|
||||
ENDIF()
|
||||
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
"${library_directory}/${library_version}" "./${library_version}"
|
||||
)
|
||||
|
||||
IF(NOT "${library_version}" STREQUAL "${library_name}")
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"${library_version}" "${library_name}"
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(NOT "${library_version}" STREQUAL "${library_soname}")
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"${library_version}" "${library_soname}"
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
# Some of the pre-built libraries come without execute bit set.
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND chmod +x "./${library_version}")
|
||||
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND ${PATCHELF_EXECUTABLE} --version
|
||||
OUTPUT_VARIABLE PATCHELF_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
STRING(REPLACE "patchelf" "" PATCHELF_VERSION "${PATCHELF_VERSION}")
|
||||
|
||||
IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND
|
||||
PATCHELF_VERSION VERSION_LESS "0.14.5")
|
||||
SET(PATCHELF_PAGE_SIZE_ARGS --page-size 65536)
|
||||
ENDIF()
|
||||
|
||||
# Patch RPATH so that we find NEEDED libraries at load time.
|
||||
IF(subdir)
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND ${PATCHELF_EXECUTABLE} ${PATCHELF_PAGE_SIZE_ARGS}
|
||||
--set-rpath "$ORIGIN/.." "./${library_version}"
|
||||
)
|
||||
ELSE()
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND ${PATCHELF_EXECUTABLE} ${PATCHELF_PAGE_SIZE_ARGS}
|
||||
--set-rpath "$ORIGIN" "./${library_version}"
|
||||
)
|
||||
ENDIF()
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue