github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/copy_in_test.go (about)

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package sql_test
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"math"
    17  	"math/rand"
    18  	"reflect"
    19  	"strconv"
    20  	"strings"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    25  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    26  	"github.com/cockroachdb/cockroach/pkg/sql/tests"
    27  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    28  	"github.com/cockroachdb/cockroach/pkg/testutils"
    29  	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
    30  	"github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
    31  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    32  	"github.com/cockroachdb/cockroach/pkg/util/timeofday"
    33  	"github.com/cockroachdb/cockroach/pkg/util/timetz"
    34  	"github.com/lib/pq"
    35  )
    36  
    37  func TestCopyNullInfNaN(t *testing.T) {
    38  	defer leaktest.AfterTest(t)()
    39  
    40  	params, _ := tests.CreateTestServerParams()
    41  	s, db, _ := serverutils.StartServer(t, params)
    42  	defer s.Stopper().Stop(context.Background())
    43  
    44  	if _, err := db.Exec(`
    45  		CREATE DATABASE d;
    46  		SET DATABASE = d;
    47  		CREATE TABLE t (
    48  			i INT NULL,
    49  			f FLOAT NULL,
    50  			s STRING NULL,
    51  			b BYTES NULL,
    52  			d DATE NULL,
    53  			t TIME NULL,
    54  			ttz TIME NULL,
    55  			ts TIMESTAMP NULL,
    56  			n INTERVAL NULL,
    57  			o BOOL NULL,
    58  			e DECIMAL NULL,
    59  			u UUID NULL,
    60  			ip INET NULL,
    61  			tz TIMESTAMPTZ NULL,
    62  			geography GEOGRAPHY NULL,
    63  			geometry GEOMETRY NULL
    64  		);
    65  	`); err != nil {
    66  		t.Fatal(err)
    67  	}
    68  
    69  	txn, err := db.Begin()
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  
    74  	stmt, err := txn.Prepare(pq.CopyIn(
    75  		"t", "i", "f", "s", "b", "d", "t", "ttz",
    76  		"ts", "n", "o", "e", "u", "ip", "tz", "geography", "geometry"))
    77  	if err != nil {
    78  		t.Fatal(err)
    79  	}
    80  
    81  	input := [][]interface{}{
    82  		{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
    83  		{nil, math.Inf(1), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
    84  		{nil, math.Inf(-1), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
    85  		{nil, math.NaN(), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
    86  	}
    87  
    88  	for _, in := range input {
    89  		_, err = stmt.Exec(in...)
    90  		if err != nil {
    91  			t.Fatal(err)
    92  		}
    93  	}
    94  	_, err = stmt.Exec()
    95  	if err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	err = stmt.Close()
    99  	if err != nil {
   100  		t.Fatal(err)
   101  	}
   102  	err = txn.Commit()
   103  	if err != nil {
   104  		t.Fatal(err)
   105  	}
   106  
   107  	rows, err := db.Query("SELECT * FROM t")
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	defer rows.Close()
   112  
   113  	for row, in := range input {
   114  		if !rows.Next() {
   115  			t.Fatal("expected more results")
   116  		}
   117  		data := make([]interface{}, len(in))
   118  		for i := range data {
   119  			data[i] = new(interface{})
   120  		}
   121  		if err := rows.Scan(data...); err != nil {
   122  			t.Fatal(err)
   123  		}
   124  		for i, d := range data {
   125  			v := d.(*interface{})
   126  			d = *v
   127  			if a, b := fmt.Sprintf("%#v", d), fmt.Sprintf("%#v", in[i]); a != b {
   128  				t.Fatalf("row %v, col %v: got %#v (%T), expected %#v (%T)", row, i, d, d, in[i], in[i])
   129  			}
   130  		}
   131  	}
   132  }
   133  
   134  // TestCopyRandom inserts random rows using COPY and ensures the SELECT'd
   135  // data is the same.
   136  func TestCopyRandom(t *testing.T) {
   137  	defer leaktest.AfterTest(t)()
   138  
   139  	params, _ := tests.CreateTestServerParams()
   140  	s, db, _ := serverutils.StartServer(t, params)
   141  	defer s.Stopper().Stop(context.Background())
   142  
   143  	if _, err := db.Exec(`
   144  		CREATE DATABASE d;
   145  		CREATE TABLE IF NOT EXISTS d.t (
   146  			id INT PRIMARY KEY,
   147  			n INTERVAL,
   148  			o BOOL,
   149  			i INT,
   150  			f FLOAT,
   151  			e DECIMAL,
   152  			t TIME,
   153  			ttz TIMETZ,
   154  			ts TIMESTAMP,
   155  			s STRING,
   156  			b BYTES,
   157  			u UUID,
   158  			ip INET,
   159  			tz TIMESTAMPTZ,
   160  			geography GEOGRAPHY NULL,
   161  			geometry GEOMETRY NULL
   162  		);
   163  		SET extra_float_digits = 3; -- to preserve floats entirely
   164  	`); err != nil {
   165  		t.Fatal(err)
   166  	}
   167  
   168  	txn, err := db.Begin()
   169  	if err != nil {
   170  		t.Fatal(err)
   171  	}
   172  
   173  	stmt, err := txn.Prepare(pq.CopyInSchema("d", "t", "id", "n", "o", "i", "f", "e", "t", "ttz", "ts", "s", "b", "u", "ip", "tz", "geography", "geometry"))
   174  	if err != nil {
   175  		t.Fatal(err)
   176  	}
   177  
   178  	rng := rand.New(rand.NewSource(0))
   179  	typs := []*types.T{
   180  		types.Int,
   181  		types.Interval,
   182  		types.Bool,
   183  		types.Int,
   184  		types.Float,
   185  		types.Decimal,
   186  		types.Time,
   187  		types.TimeTZ,
   188  		types.Timestamp,
   189  		types.String,
   190  		types.Bytes,
   191  		types.Uuid,
   192  		types.INet,
   193  		types.TimestampTZ,
   194  		types.Geography,
   195  		types.Geometry,
   196  	}
   197  
   198  	var inputs [][]interface{}
   199  
   200  	for i := 0; i < 1000; i++ {
   201  		row := make([]interface{}, len(typs))
   202  		for j, t := range typs {
   203  			var ds string
   204  			if j == 0 {
   205  				// Special handling for ID field
   206  				ds = strconv.Itoa(i)
   207  			} else {
   208  				d := sqlbase.RandDatum(rng, t, false)
   209  				ds = tree.AsStringWithFlags(d, tree.FmtBareStrings)
   210  				switch t {
   211  				case types.Float:
   212  					ds = strings.TrimSuffix(ds, ".0")
   213  				}
   214  			}
   215  			row[j] = ds
   216  		}
   217  		_, err = stmt.Exec(row...)
   218  		if err != nil {
   219  			t.Fatal(err)
   220  		}
   221  		inputs = append(inputs, row)
   222  	}
   223  
   224  	err = stmt.Close()
   225  	if err != nil {
   226  		t.Fatal(err)
   227  	}
   228  	err = txn.Commit()
   229  	if err != nil {
   230  		t.Fatal(err)
   231  	}
   232  
   233  	rows, err := db.Query("SELECT * FROM d.t ORDER BY id")
   234  	if err != nil {
   235  		t.Fatal(err)
   236  	}
   237  	defer rows.Close()
   238  
   239  	for row, in := range inputs {
   240  		if !rows.Next() {
   241  			t.Fatal("expected more results")
   242  		}
   243  		data := make([]interface{}, len(in))
   244  		for i := range data {
   245  			data[i] = new(interface{})
   246  		}
   247  		if err := rows.Scan(data...); err != nil {
   248  			t.Fatal(err)
   249  		}
   250  		for i, d := range data {
   251  			v := d.(*interface{})
   252  			d := *v
   253  			ds := fmt.Sprint(d)
   254  			switch d := d.(type) {
   255  			case []byte:
   256  				ds = string(d)
   257  			case time.Time:
   258  				var dt tree.NodeFormatter
   259  				if typs[i].Family() == types.TimeFamily {
   260  					dt = tree.MakeDTime(timeofday.FromTimeAllow2400(d))
   261  				} else if typs[i].Family() == types.TimeTZFamily {
   262  					dt = tree.NewDTimeTZ(timetz.MakeTimeTZFromTimeAllow2400(d))
   263  				} else {
   264  					dt = tree.MustMakeDTimestamp(d, time.Microsecond)
   265  				}
   266  				ds = tree.AsStringWithFlags(dt, tree.FmtBareStrings)
   267  			}
   268  			if !reflect.DeepEqual(in[i], ds) {
   269  				t.Fatalf("row %v, col %v: got %#v (%T), expected %#v", row, i, ds, d, in[i])
   270  			}
   271  		}
   272  	}
   273  }
   274  
   275  func TestCopyError(t *testing.T) {
   276  	defer leaktest.AfterTest(t)()
   277  
   278  	params, _ := tests.CreateTestServerParams()
   279  	s, db, _ := serverutils.StartServer(t, params)
   280  	defer s.Stopper().Stop(context.Background())
   281  
   282  	if _, err := db.Exec(`
   283  		CREATE DATABASE d;
   284  		SET DATABASE = d;
   285  		CREATE TABLE t (
   286  			i INT PRIMARY KEY
   287  		);
   288  	`); err != nil {
   289  		t.Fatal(err)
   290  	}
   291  
   292  	txn, err := db.Begin()
   293  	if err != nil {
   294  		t.Fatal(err)
   295  	}
   296  
   297  	stmt, err := txn.Prepare(pq.CopyIn("t", "i"))
   298  	if err != nil {
   299  		t.Fatal(err)
   300  	}
   301  
   302  	// Insert conflicting primary keys.
   303  	for i := 0; i < 2; i++ {
   304  		_, err = stmt.Exec(1)
   305  		if err != nil {
   306  			t.Fatal(err)
   307  		}
   308  	}
   309  
   310  	err = stmt.Close()
   311  	if err == nil {
   312  		t.Fatal("expected error")
   313  	}
   314  
   315  	// Make sure we can query after an error.
   316  	var i int
   317  	if err := db.QueryRow("SELECT 1").Scan(&i); err != nil {
   318  		t.Fatal(err)
   319  	} else if i != 1 {
   320  		t.Fatalf("expected 1, got %d", i)
   321  	}
   322  	if err := txn.Rollback(); err != nil {
   323  		t.Fatal(err)
   324  	}
   325  }
   326  
   327  // TestCopyOne verifies that only one COPY can run at once.
   328  func TestCopyOne(t *testing.T) {
   329  	defer leaktest.AfterTest(t)()
   330  
   331  	t.Skip("#18352")
   332  
   333  	params, _ := tests.CreateTestServerParams()
   334  	s, db, _ := serverutils.StartServer(t, params)
   335  	defer s.Stopper().Stop(context.Background())
   336  
   337  	if _, err := db.Exec(`
   338  		CREATE DATABASE d;
   339  		SET DATABASE = d;
   340  		CREATE TABLE t (
   341  			i INT PRIMARY KEY
   342  		);
   343  	`); err != nil {
   344  		t.Fatal(err)
   345  	}
   346  
   347  	txn, err := db.Begin()
   348  	if err != nil {
   349  		t.Fatal(err)
   350  	}
   351  
   352  	if _, err := txn.Prepare(pq.CopyIn("t", "i")); err != nil {
   353  		t.Fatal(err)
   354  	}
   355  	if _, err := txn.Prepare(pq.CopyIn("t", "i")); err == nil {
   356  		t.Fatal("expected error")
   357  	}
   358  }
   359  
   360  // TestCopyInProgress verifies that after a COPY has started another statement
   361  // cannot run.
   362  func TestCopyInProgress(t *testing.T) {
   363  	defer leaktest.AfterTest(t)()
   364  
   365  	t.Skip("#18352")
   366  
   367  	params, _ := tests.CreateTestServerParams()
   368  	s, db, _ := serverutils.StartServer(t, params)
   369  	defer s.Stopper().Stop(context.Background())
   370  
   371  	if _, err := db.Exec(`
   372  		CREATE DATABASE d;
   373  		SET DATABASE = d;
   374  		CREATE TABLE t (
   375  			i INT PRIMARY KEY
   376  		);
   377  	`); err != nil {
   378  		t.Fatal(err)
   379  	}
   380  
   381  	txn, err := db.Begin()
   382  	if err != nil {
   383  		t.Fatal(err)
   384  	}
   385  
   386  	if _, err := txn.Prepare(pq.CopyIn("t", "i")); err != nil {
   387  		t.Fatal(err)
   388  	}
   389  
   390  	if _, err := txn.Query("SELECT 1"); err == nil {
   391  		t.Fatal("expected error")
   392  	}
   393  }
   394  
   395  // TestCopyTransaction verifies that COPY data can be used after it is done
   396  // within a transaction.
   397  func TestCopyTransaction(t *testing.T) {
   398  	defer leaktest.AfterTest(t)()
   399  
   400  	params, _ := tests.CreateTestServerParams()
   401  	s, db, _ := serverutils.StartServer(t, params)
   402  	defer s.Stopper().Stop(context.Background())
   403  
   404  	if _, err := db.Exec(`
   405  		CREATE DATABASE d;
   406  		SET DATABASE = d;
   407  		CREATE TABLE t (
   408  			i INT PRIMARY KEY
   409  		);
   410  	`); err != nil {
   411  		t.Fatal(err)
   412  	}
   413  
   414  	txn, err := db.Begin()
   415  	if err != nil {
   416  		t.Fatal(err)
   417  	}
   418  
   419  	// Note that, at least with lib/pq, this doesn't actually send a Parse msg
   420  	// (which we wouldn't support, as we don't support Copy-in in extended
   421  	// protocol mode). lib/pq has magic for recognizing a Copy.
   422  	stmt, err := txn.Prepare(pq.CopyIn("t", "i"))
   423  	if err != nil {
   424  		t.Fatal(err)
   425  	}
   426  
   427  	const val = 2
   428  
   429  	_, err = stmt.Exec(val)
   430  	if err != nil {
   431  		t.Fatal(err)
   432  	}
   433  
   434  	if err = stmt.Close(); err != nil {
   435  		t.Fatal(err)
   436  	}
   437  
   438  	var i int
   439  	if err := txn.QueryRow("SELECT i FROM d.t").Scan(&i); err != nil {
   440  		t.Fatal(err)
   441  	} else if i != val {
   442  		t.Fatalf("expected 1, got %d", i)
   443  	}
   444  	if err := txn.Commit(); err != nil {
   445  		t.Fatal(err)
   446  	}
   447  }
   448  
   449  // TestCopyFKCheck verifies that foreign keys are checked during COPY.
   450  func TestCopyFKCheck(t *testing.T) {
   451  	defer leaktest.AfterTest(t)()
   452  
   453  	params, _ := tests.CreateTestServerParams()
   454  	s, db, _ := serverutils.StartServer(t, params)
   455  	defer s.Stopper().Stop(context.Background())
   456  
   457  	db.SetMaxOpenConns(1)
   458  	r := sqlutils.MakeSQLRunner(db)
   459  	r.Exec(t, `
   460  		CREATE DATABASE d;
   461  		SET DATABASE = d;
   462  		CREATE TABLE p (p INT PRIMARY KEY);
   463  		CREATE TABLE t (
   464  		  a INT PRIMARY KEY,
   465  		  p INT REFERENCES p(p)
   466  		);
   467  		SET optimizer_foreign_keys = true;
   468  	`)
   469  
   470  	txn, err := db.Begin()
   471  	if err != nil {
   472  		t.Fatal(err)
   473  	}
   474  	defer func() { _ = txn.Rollback() }()
   475  
   476  	stmt, err := txn.Prepare(pq.CopyIn("t", "a", "p"))
   477  	if err != nil {
   478  		t.Fatal(err)
   479  	}
   480  
   481  	_, err = stmt.Exec(1, 1)
   482  	if err != nil {
   483  		t.Fatal(err)
   484  	}
   485  
   486  	err = stmt.Close()
   487  	if !testutils.IsError(err, "foreign key violation|violates foreign key constraint") {
   488  		t.Fatalf("expected FK error, got: %v", err)
   489  	}
   490  }