mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-16 16:23:30 +00:00
Compare commits
10 Commits
PMM-11406-
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
![]() |
11e73c8b60 | ||
![]() |
2dbdb8642b | ||
![]() |
cd6183dbcc | ||
![]() |
2ac8385d2d | ||
![]() |
128dc2938e | ||
![]() |
f550652dbf | ||
![]() |
fef02540fe | ||
![]() |
4e190a34ef | ||
![]() |
21fd4f7b90 | ||
![]() |
20b3196cda |
@@ -3515,12 +3515,12 @@ use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
my %alt_val_for = (
|
||||
ON => 1,
|
||||
YES => 1,
|
||||
TRUE => 1,
|
||||
OFF => 0,
|
||||
NO => 0,
|
||||
FALSE => 0,
|
||||
ON => 1,
|
||||
YES => 1,
|
||||
TRUE => 1,
|
||||
OFF => 0,
|
||||
NO => 0,
|
||||
FALSE => 0,
|
||||
);
|
||||
|
||||
sub new {
|
||||
@@ -3637,7 +3637,8 @@ sub diff {
|
||||
next CONFIG if $val0 == $valN;
|
||||
}
|
||||
else {
|
||||
next CONFIG if $ignore_case
|
||||
|
||||
next CONFIG if $ignore_case
|
||||
? lc($val0) eq lc($valN)
|
||||
: $val0 eq $valN;
|
||||
|
||||
@@ -3699,7 +3700,7 @@ sub _normalize_value {
|
||||
my ($val, $is_dir, $base_path) = @args{qw(value is_directory base_path)};
|
||||
|
||||
$val = defined $val ? $val : '';
|
||||
$val = $alt_val_for{$val} if exists $alt_val_for{$val};
|
||||
$val = $alt_val_for{uc($val)} if exists $alt_val_for{uc($val)};
|
||||
|
||||
if ( $val =~ m/,/ && !$is_dir && !$base_path) {
|
||||
$val = join(',', sort(split(',', $val)));
|
||||
|
@@ -11211,7 +11211,7 @@ sub get_unique_index_fields {
|
||||
$clean .= $suffix;
|
||||
|
||||
my $fields = [];
|
||||
my $fields_re = qr/\s(?:PRIMARY|UNIQUE)\s+(?:INDEX|KEY|)\s*(?:.*?)\s*\((.*?)\)/i;
|
||||
my $fields_re = qr/\s(?:(?:(?:PRIMARY|UNIQUE)\s+(?:INDEX|KEY|))|UNIQUE)\s*(?:.*?)\s*\((.*?)\)/i;
|
||||
|
||||
while($clean =~ /$fields_re/g) {
|
||||
push @$fields, [ split /\s*,\s*/, $1 ];
|
||||
|
@@ -12965,14 +12965,43 @@ Possible methods are:
|
||||
=========== ==================
|
||||
processlist SHOW PROCESSLIST
|
||||
hosts SHOW REPLICAS (SHOW SLAVE HOSTS before MySQL 8.1)
|
||||
dsn=DSN DSNs from a table
|
||||
none Do not find replicas
|
||||
|
||||
The processlist method is preferred because SHOW REPLICAS is not reliable.
|
||||
However, the hosts method is required if the server uses a non-standard
|
||||
port (not 3306). Usually pt-table-sync does the right thing and finds
|
||||
the replicas, but you may give a preferred method and it will be used first.
|
||||
If it doesn't find any replicas, the other methods will be tried.
|
||||
The C<processlist> method is the default, because C<SHOW REPLICAS> is not
|
||||
reliable. However, if the server uses a non-standard port (not 3306), then
|
||||
the C<hosts> method becomes the default because it works better in this case.
|
||||
|
||||
The C<hosts> method requires replicas to be configured with C<report_host>,
|
||||
C<report_port>, etc.
|
||||
|
||||
The C<dsn> method is special: rather than automatically discovering replicas,
|
||||
this method specifies a table with replica DSNs. The tool will only connect
|
||||
to these replicas. This method works best when replicas do not use the same
|
||||
MySQL username or password as the source, or when you want to prevent the tool
|
||||
from connecting to certain replicas. The C<dsn> method is specified like:
|
||||
C<--recursion-method dsn=h=host,D=percona,t=dsns>. The specified DSN must
|
||||
have D and t parts, or just a database-qualified t part, which specify the
|
||||
DSN table. The DSN table must have the following structure:
|
||||
|
||||
CREATE TABLE `dsns` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`dsn` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
DSNs are ordered by C<id>, but C<id> and C<parent_id> are otherwise ignored.
|
||||
The C<dsn> column contains a replica DSN like it would be given on the command
|
||||
line, for example: C<"h=replica_host,u=repl_user,p=repl_pass">.
|
||||
|
||||
The C<none> method makes the tool ignore all replicas and cluster nodes. This
|
||||
method is not recommended because it effectively disables the
|
||||
L<"REPLICA CHECKS"> and no differences can be found. It is useful, however, if
|
||||
you only need to write checksums on the source or a single cluster node. The
|
||||
safer alternative is C<--no-replicate-check>: the tool finds replicas and
|
||||
cluster nodes, performs the L<"REPLICA CHECKS">, but does not check for
|
||||
differences. See L<"--[no]replicate-check">.
|
||||
|
||||
=item --replace
|
||||
|
||||
|
12
go.mod
12
go.mod
@@ -29,7 +29,7 @@ require (
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/xlab/treeprint v1.2.0
|
||||
go.mongodb.org/mongo-driver v1.17.4
|
||||
golang.org/x/crypto v0.41.0
|
||||
golang.org/x/crypto v0.42.0
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
|
||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
@@ -62,11 +62,11 @@ require (
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/sys v0.36.0 // indirect
|
||||
golang.org/x/term v0.35.0 // indirect
|
||||
golang.org/x/text v0.29.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apimachinery v0.34.0 // indirect
|
||||
|
24
go.sum
24
go.sum
@@ -131,8 +131,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@@ -146,15 +146,15 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -170,18 +170,18 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
|
@@ -31,12 +31,12 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
# in SHOW VARS as var=TRUE. I.e. there's several synonyms for basic
|
||||
# true (1) and false (0), so we normalize them to make comparisons easier.
|
||||
my %alt_val_for = (
|
||||
ON => 1,
|
||||
YES => 1,
|
||||
TRUE => 1,
|
||||
OFF => 0,
|
||||
NO => 0,
|
||||
FALSE => 0,
|
||||
ON => 1,
|
||||
YES => 1,
|
||||
TRUE => 1,
|
||||
OFF => 0,
|
||||
NO => 0,
|
||||
FALSE => 0,
|
||||
);
|
||||
|
||||
# Sub: new
|
||||
@@ -202,7 +202,8 @@ sub diff {
|
||||
next CONFIG if $val0 == $valN;
|
||||
}
|
||||
else {
|
||||
next CONFIG if $ignore_case
|
||||
|
||||
next CONFIG if $ignore_case
|
||||
? lc($val0) eq lc($valN)
|
||||
: $val0 eq $valN;
|
||||
|
||||
@@ -293,7 +294,7 @@ sub _normalize_value {
|
||||
my ($val, $is_dir, $base_path) = @args{qw(value is_directory base_path)};
|
||||
|
||||
$val = defined $val ? $val : '';
|
||||
$val = $alt_val_for{$val} if exists $alt_val_for{$val};
|
||||
$val = $alt_val_for{uc($val)} if exists $alt_val_for{uc($val)};
|
||||
|
||||
if ( $val =~ m/,/ && !$is_dir && !$base_path) {
|
||||
$val = join(',', sort(split(',', $val)));
|
||||
|
@@ -208,7 +208,7 @@ func main() {
|
||||
if err != nil {
|
||||
log.Infof("cannot check version updates: %s", err.Error())
|
||||
} else if advice != "" {
|
||||
log.Infof("%s", advice)
|
||||
log.Infof(advice)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,6 +373,24 @@ func getHostInfo(ctx context.Context, client *mongo.Client) (*hostInfo, error) {
|
||||
return nil, errors.Wrap(err, "GetHostInfo.hostInfo")
|
||||
}
|
||||
|
||||
cmdOpts := proto.CommandLineOptions{}
|
||||
query := primitive.D{{Key: "getCmdLineOpts", Value: 1}}
|
||||
err := client.Database("admin").RunCommand(ctx, query).Decode(&cmdOpts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot get command line options")
|
||||
}
|
||||
|
||||
ss := proto.ServerStatus{}
|
||||
query = primitive.D{{Key: "serverStatus", Value: 1}}
|
||||
if err := client.Database("admin").RunCommand(ctx, query).Decode(&ss); err != nil {
|
||||
return nil, errors.Wrap(err, "GetHostInfo.serverStatus")
|
||||
}
|
||||
|
||||
pi := procInfo{}
|
||||
if err := getProcInfo(int32(ss.Pid), &pi); err != nil {
|
||||
pi.Error = err
|
||||
}
|
||||
|
||||
nodeType, _ := getNodeType(ctx, client)
|
||||
procCount, _ := countMongodProcesses()
|
||||
|
||||
@@ -380,41 +398,24 @@ func getHostInfo(ctx context.Context, client *mongo.Client) (*hostInfo, error) {
|
||||
Hostname: hi.System.Hostname,
|
||||
HostOsType: hi.Os.Type,
|
||||
HostSystemCPUArch: hi.System.CpuArch,
|
||||
ProcProcessCount: procCount,
|
||||
NodeType: nodeType,
|
||||
CmdlineArgs: nil,
|
||||
DBPath: "", // Sets default. It will be overridden later if necessary
|
||||
|
||||
ProcessName: ss.Process,
|
||||
ProcProcessCount: procCount,
|
||||
Version: ss.Version,
|
||||
NodeType: nodeType,
|
||||
|
||||
ProcPath: pi.Path,
|
||||
ProcUserName: pi.UserName,
|
||||
ProcCreateTime: pi.CreateTime,
|
||||
CmdlineArgs: cmdOpts.Argv,
|
||||
}
|
||||
if ss.Repl != nil {
|
||||
i.ReplicasetName = ss.Repl.SetName
|
||||
}
|
||||
|
||||
var cmdOpts proto.CommandLineOptions
|
||||
query := primitive.D{{Key: "getCmdLineOpts", Value: 1}}
|
||||
err := client.Database("admin").RunCommand(ctx, query).Decode(&cmdOpts)
|
||||
if err == nil {
|
||||
if len(cmdOpts.Argv) > 0 {
|
||||
i.CmdlineArgs = cmdOpts.Argv
|
||||
}
|
||||
if cmdOpts.Parsed.Storage.DbPath != "" {
|
||||
i.DBPath = cmdOpts.Parsed.Storage.DbPath
|
||||
}
|
||||
}
|
||||
|
||||
var ss proto.ServerStatus
|
||||
query = primitive.D{{Key: "serverStatus", Value: 1}}
|
||||
err = client.Database("admin").RunCommand(ctx, query).Decode(&ss)
|
||||
if err == nil {
|
||||
i.ProcessName = ss.Process
|
||||
i.Version = ss.Version
|
||||
if ss.Repl != nil {
|
||||
i.ReplicasetName = ss.Repl.SetName
|
||||
}
|
||||
|
||||
pi := procInfo{}
|
||||
if err := getProcInfo(int32(ss.Pid), &pi); err != nil {
|
||||
pi.Error = err
|
||||
} else {
|
||||
i.ProcPath = pi.Path
|
||||
i.ProcUserName = pi.UserName
|
||||
i.ProcCreateTime = pi.CreateTime
|
||||
}
|
||||
if cmdOpts.Parsed.Storage.DbPath != "" {
|
||||
i.DBPath = cmdOpts.Parsed.Storage.DbPath
|
||||
}
|
||||
|
||||
return i, nil
|
||||
|
@@ -8,9 +8,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pborman/getopt"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
tu "github.com/percona/percona-toolkit/src/go/internal/testutils"
|
||||
"github.com/percona/percona-toolkit/src/go/mongolib/proto"
|
||||
)
|
||||
|
||||
func TestGetHostInfo(t *testing.T) {
|
||||
@@ -49,26 +49,6 @@ func TestGetHostInfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetHostInfoResult(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
client, err := tu.TestClient(ctx, tu.MongoDBShard1PrimaryPort)
|
||||
assert.NoError(err, "cannot get a new MongoDB client")
|
||||
|
||||
host, err := getHostInfo(ctx, client)
|
||||
assert.NoError(err, "getHostInfo error")
|
||||
|
||||
// With the current setup, we should get this information.
|
||||
assert.NotEmpty(host.ProcessName, "ProcessName should not be empty if serverStatus succeeds")
|
||||
assert.NotEmpty(host.Version, "Version should not be empty if serverStatus succeeds")
|
||||
assert.NotEmpty(host.ProcPath, "ProcPath should not be empty if getProcInfo succeeds")
|
||||
assert.NotEmpty(host.ProcUserName, "ProcUserName should not be empty if getProcInfo succeeds")
|
||||
assert.False(host.ProcCreateTime.IsZero(), "ProcCreateTime should not be zero if getProcInfo succeeds")
|
||||
}
|
||||
|
||||
func TestClusterWideInfo(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -105,6 +85,16 @@ func TestClusterWideInfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func addToCounters(ss proto.ServerStatus, increment int64) proto.ServerStatus {
|
||||
ss.Opcounters.Command += increment
|
||||
ss.Opcounters.Delete += increment
|
||||
ss.Opcounters.GetMore += increment
|
||||
ss.Opcounters.Insert += increment
|
||||
ss.Opcounters.Query += increment
|
||||
ss.Opcounters.Update += increment
|
||||
return ss
|
||||
}
|
||||
|
||||
func TestParseArgs(t *testing.T) {
|
||||
tests := []struct {
|
||||
args []string
|
||||
|
@@ -449,6 +449,30 @@ is_deeply(
|
||||
"..but can be turned off"
|
||||
);
|
||||
|
||||
# ############################################################################
|
||||
# https://perconadev.atlassian.net/browse/PT-2014
|
||||
# pt-config-diff does not honor case insensitivity flag for boolean values
|
||||
# ############################################################################
|
||||
$c1 = new MySQLConfig(
|
||||
file => "$trunk/$sample/pt-2014-1.txt",
|
||||
TextResultSetParser => $trp,
|
||||
);
|
||||
$c2 = new MySQLConfig(
|
||||
file => "$trunk/$sample/pt-2014-2.txt",
|
||||
TextResultSetParser => $trp,
|
||||
);
|
||||
{
|
||||
my $diff = $cc->diff(
|
||||
configs => [$c1, $c2],
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
$diff,
|
||||
undef,
|
||||
"Boolean values are the same regardless of the case"
|
||||
) or diag(Dumper($diff));
|
||||
}
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
7
t/lib/samples/configs/pt-2014-1.txt
Normal file
7
t/lib/samples/configs/pt-2014-1.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
[mysqld]
|
||||
log_bin=1
|
||||
gtid_mode=on
|
||||
read_only=off
|
||||
autocommit=no
|
||||
binlog_format=mixed
|
||||
skip_name_resolve=true
|
7
t/lib/samples/configs/pt-2014-2.txt
Normal file
7
t/lib/samples/configs/pt-2014-2.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
[mysqld]
|
||||
log_bin=on
|
||||
gtid_mode=True
|
||||
read_only=FALSE
|
||||
autocommit=0
|
||||
binlog_format=MIXED
|
||||
skip_name_resolve=TRUE
|
@@ -19,7 +19,7 @@ use Sandbox;
|
||||
use SqlModes;
|
||||
use File::Temp qw/ tempdir /;
|
||||
|
||||
plan tests => 6;
|
||||
plan tests => 10;
|
||||
|
||||
require "$trunk/bin/pt-online-schema-change";
|
||||
|
||||
@@ -44,7 +44,7 @@ $sb->load_file('source', "$sample/pt-153.sql");
|
||||
|
||||
($output, $exit_status) = full_output(
|
||||
sub { pt_online_schema_change::main(@args, "$source_dsn,D=test,t=t1",
|
||||
'--execute',
|
||||
'--execute',
|
||||
'--alter', "ADD UNIQUE INDEX c1 (f2, f3)",
|
||||
),
|
||||
},
|
||||
@@ -64,7 +64,7 @@ like(
|
||||
|
||||
($output, $exit_status) = full_output(
|
||||
sub { pt_online_schema_change::main(@args, "$source_dsn,D=test,t=t1",
|
||||
'--execute',
|
||||
'--execute',
|
||||
'--alter', "ADD UNIQUE INDEX c1 (f2, f3), PRIMARY KEY (f3), UNIQUE KEY k2 (f3)",
|
||||
),
|
||||
},
|
||||
@@ -88,6 +88,47 @@ like(
|
||||
"PT-153 Adding multiple unique indexes -> multime example queries.",
|
||||
);
|
||||
|
||||
# UNIQUE is possible without INDEX or KEY, we need to check this as well.
|
||||
($output, $exit_status) = full_output(
|
||||
sub { pt_online_schema_change::main(@args, "$source_dsn,D=test,t=t1",
|
||||
'--execute',
|
||||
'--alter', "ADD UNIQUE c1 (f2, f3)",
|
||||
),
|
||||
},
|
||||
);
|
||||
|
||||
isnt(
|
||||
$exit_status,
|
||||
0,
|
||||
"PT-153 Adding unique index without index/key keyword exit status != 0.",
|
||||
);
|
||||
|
||||
like(
|
||||
$output,
|
||||
qr/You are trying to add an unique key. This can result in data loss if the data is not unique/s,
|
||||
"PT-153 Adding unique index without index/key keyword warning message.",
|
||||
);
|
||||
|
||||
($output, $exit_status) = full_output(
|
||||
sub { pt_online_schema_change::main(@args, "$source_dsn,D=test,t=t1",
|
||||
'--execute',
|
||||
'--alter', "ADD UNIQUE(f2, f3)",
|
||||
),
|
||||
},
|
||||
);
|
||||
|
||||
isnt(
|
||||
$exit_status,
|
||||
0,
|
||||
"PT-153 Adding unique index without index/key keyword and index name exit status != 0.",
|
||||
);
|
||||
|
||||
like(
|
||||
$output,
|
||||
qr/You are trying to add an unique key. This can result in data loss if the data is not unique/s,
|
||||
"PT-153 Adding unique index without index/key keyword and index name warning message.",
|
||||
);
|
||||
|
||||
$source_dbh->do("DROP DATABASE IF EXISTS test");
|
||||
|
||||
# #############################################################################
|
||||
|
@@ -44,16 +44,16 @@ $output = `$trunk/bin/pt-table-sync --sync-to-source h=127.1,P=12346,u=msandbox,
|
||||
# and EXPLAIN does not guarantee accuracy of results.
|
||||
like(
|
||||
$output,
|
||||
qr/FROM `issue_375`.`t` FORCE INDEX \(`updated_at`\) WHERE \(`updated_at` > 0 AND `updated_at` < '2009-09-05 02:\d\d:\d\d'/,
|
||||
qr/FROM `issue_375`.`t` FORCE INDEX \(`updated_at`\) WHERE \(`updated_at` > 0 AND `updated_at` < '2009-09-05 \d\d:\d\d:\d\d'/,
|
||||
'--chunk-index',
|
||||
);
|
||||
) or diag($output);
|
||||
|
||||
$output = `$trunk/bin/pt-table-sync --sync-to-source h=127.1,P=12346,u=msandbox,p=msandbox -d issue_375 --print -v -v --chunk-size 50 --chunk-column updated_at`;
|
||||
like(
|
||||
$output,
|
||||
qr/FROM `issue_375`.`t` FORCE INDEX \(`updated_at`\) WHERE \(`updated_at` > 0 AND `updated_at` < '2009-09-05 02:\d\d:\d\d'/,
|
||||
qr/FROM `issue_375`.`t` FORCE INDEX \(`updated_at`\) WHERE \(`updated_at` > 0 AND `updated_at` < '2009-09-05 \d\d:\d\d:\d\d'/,
|
||||
'--chunk-column',
|
||||
);
|
||||
) or diag($output);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
|
Reference in New Issue
Block a user