Example #1
0
func TestTransactionClone(t *testing.T) {
	txn := nonZeroTxn.Clone()

	fields := util.EqualPtrFields(reflect.ValueOf(nonZeroTxn), reflect.ValueOf(txn), "")
	sort.Strings(fields)

	// Verify that the only equal pointer fields after cloning are the ones
	// listed below. If this test fails, please update the list below and/or
	// Transaction.Clone().
	expFields := []string{
		"Intents.EndKey",
		"Intents.Key",
		"TxnMeta.ID",
		"TxnMeta.Key",
	}
	if !reflect.DeepEqual(expFields, fields) {
		t.Fatalf("%s != %s", expFields, fields)
	}
}
Example #2
0
func TestDeepCopy(t *testing.T) {
	testExprs := []string{
		"1",
		"1 + 2",
		"a = 1",
		// Bitwise operators.
		`1 & 3`,
		`1 | 3`,
		`1 ^ 3`,
		// Arithmetic operators.
		`1 + 1`,
		`1 - 2`,
		`3 * 4`,
		`3.1 % 2.0`,
		`5 % 3`,
		`1 + NULL`,
		`1.1::decimal + 2.4::decimal`,
		`1.1::decimal - 2.4::decimal`,
		`1.1::decimal * 2.4::decimal`,
		`1.1::decimal % 2.4::decimal`,
		// Division is always done on floats or decimals.
		`4 / 5`,
		`1.0 / 0.0`,
		`-1.0 * (1.0 / 0.0)`,
		`1.1::decimal / 2.2::decimal`,
		// Grouping
		`1 + 2 + (3 * 4)`,
		// Unary operators.
		`-3`,
		`-4.1`,
		`-6.1::decimal`,
		// Ones complement operates on signed integers.
		`~0`,
		`~0 - 1`,
		// Hexadecimal numbers.
		`0xa`,
		// String concatenation.
		`'a' || 'b'`,
		`'a' || (1 + 2)::char`,
		// Bit shift operators.
		`1 << 2`,
		`4 >> 2`,
		// Boolean expressions.
		`false AND true`,
		`false AND NULL`,
		`false AND false`,
		`true AND true`,
		`true AND false`,
		`true AND NULL`,
		`NULL AND true`,
		`NULL AND false`,
		`NULL AND NULL`,
		`false OR true`,
		`false OR NULL`,
		`false OR false`,
		`true OR true`,
		`true OR false`,
		`true OR NULL`,
		`NULL OR true`,
		`NULL OR false`,
		`NULL OR NULL`,
		`NOT false`,
		`NOT true`,
		`NOT NULL`,
		// Boolean expressions short-circuit the evaluation.
		`false AND (a = 1)`,
		`true OR (a = 1)`,
		// Comparisons.
		`0 = 1`,
		`0 != 1`,
		`0 < 1`,
		`0 <= 1`,
		`0 > 1`,
		`0 >= 1`,
		`true = false`,
		`true != false`,
		`true < false`,
		`true <= false`,
		`true > false`,
		`true >= false`,
		`'a' = 'b'`,
		`'a' != 'b'`,
		`'a' < 'b'`,
		`'a' <= 'b'`,
		`'a' > 'b'`,
		`'a' >= 'b'`,
		`'a' >= 'b'`,
		`'10' > '2'`,
		`1.1 = 1.2`,
		`1.1 != 1.2`,
		`1.1 < 1.2`,
		`1.1 <= 1.2`,
		`1.1 > 1.2`,
		`1.1 >= 1.2`,
		`1.1::decimal = 1.2::decimal`,
		`1.1::decimal != 1.2::decimal`,
		`1.1::decimal < 1.2::decimal`,
		`1.1::decimal <= 1.2::decimal`,
		`1.1::decimal > 1.2::decimal`,
		`1.1::decimal >= 1.2::decimal`,
		`'2015-10-01'::date = '2015-10-02'::date`,
		`'2015-10-01'::date != '2015-10-02'::date`,
		`'2015-10-01'::date < '2015-10-02'::date`,
		`'2015-10-01'::date <= '2015-10-02'::date`,
		`'2015-10-01'::date > '2015-10-02'::date`,
		`'2015-10-01'::date >= '2015-10-02'::date`,
		`'2015-10-01'::timestamp = '2015-10-02'::timestamp`,
		`'2015-10-01'::timestamp != '2015-10-02'::timestamp`,
		`'2015-10-01'::timestamp < '2015-10-02'::timestamp`,
		`'2015-10-01'::timestamp <= '2015-10-02'::timestamp`,
		`'2015-10-01'::timestamp > '2015-10-02'::timestamp`,
		`'2015-10-01'::timestamp >= '2015-10-02'::timestamp`,
		`'12h2m1s23ms'::interval = '12h2m1s24ms'::interval`,
		`'12h2m1s23ms'::interval != '12h2m1s24ms'::interval`,
		`'12h2m1s23ms'::interval < '12h2m1s24ms'::interval`,
		`'12h2m1s23ms'::interval <= '12h2m1s24ms'::interval`,
		`'12h2m1s23ms'::interval > '12h2m1s24ms'::interval`,
		`'12h2m1s23ms'::interval >= '12h2m1s24ms'::interval`,
		// Comparisons against NULL result in NULL.
		`0 = NULL`,
		`NULL = NULL`,
		// LIKE and NOT LIKE
		`'TEST' LIKE 'TEST'`,
		`'TEST' LIKE 'TE%'`,
		`'TEST' LIKE '%E%'`,
		`'TEST' LIKE 'TES_'`,
		`'TEST' LIKE 'TE_%'`,
		`'TEST' LIKE 'TE_'`,
		`'TEST' LIKE '%'`,
		`'TEST' LIKE '%R'`,
		`'TEST' LIKE 'TESTER'`,
		`'TEST' LIKE ''`,
		`'' LIKE ''`,
		`'T' LIKE '_'`,
		`'TE' LIKE '_'`,
		`'TEST' NOT LIKE '%E%'`,
		`'TEST' NOT LIKE 'TES_'`,
		`'TEST' NOT LIKE 'TE_'`,
		// SIMILAR TO and NOT SIMILAR TO
		`'abc' SIMILAR TO 'abc'`,
		`'abc' SIMILAR TO 'a'`,
		`'abc' SIMILAR TO '%(b|d)%'`,
		`'abc' SIMILAR TO '(b|c)%'`,
		`'abc' NOT SIMILAR TO '%(b|d)%'`,
		`'abc' NOT SIMILAR TO '(b|c)%'`,
		// IS DISTINCT FROM can be used to compare NULLs "safely".
		`0 IS DISTINCT FROM 0`,
		`0 IS DISTINCT FROM 1`,
		`0 IS DISTINCT FROM NULL`,
		`NULL IS DISTINCT FROM NULL`,
		`NULL IS DISTINCT FROM 1`,
		`0 IS NOT DISTINCT FROM 0`,
		`0 IS NOT DISTINCT FROM 1`,
		`0 IS NOT DISTINCT FROM NULL`,
		`NULL IS NOT DISTINCT FROM NULL`,
		`NULL IS NOT DISTINCT FROM 1`,
		// IS expressions.
		`0 IS NULL`,
		`0 IS NOT NULL`,
		`NULL IS NULL`,
		`NULL IS NOT NULL`,
		`NULL IS UNKNOWN`,
		`NULL IS NOT UNKNOWN`,
		`TRUE IS TRUE`,
		`TRUE IS NOT TRUE`,
		`FALSE IS TRUE`,
		`FALSE IS NOT TRUE`,
		`NULL IS TRUE`,
		`NULL IS NOT TRUE`,
		`TRUE IS FALSE`,
		`TRUE IS NOT FALSE`,
		`FALSE IS FALSE`,
		`FALSE IS NOT FALSE`,
		`NULL IS FALSE`,
		`NULL IS NOT FALSE`,
		// IS OF expressions.
		`TRUE IS OF (BOOL)`,
		`1 IS OF (INT)`,
		`1.0 IS OF (FLOAT)`,
		`1.0::decimal IS OF (DECIMAL)`,
		`'hello' IS OF (STRING)`,
		`'hello' IS OF (BYTES)`,
		`b'hello' IS OF (STRING)`,
		`b'hello' IS OF (BYTES)`,
		`'2012-09-21'::date IS OF (DATE)`,
		`'2010-09-28 12:00:00.1'::timestamp IS OF (TIMESTAMP)`,
		`'34h'::interval IS OF (INTERVAL)`,
		`1 IS OF (STRING)`,
		`1 IS OF (BOOL, INT)`,
		`1 IS NOT OF (INT)`,
		`1 IS NOT OF (STRING)`,
		`1 IS NOT OF (BOOL, INT)`,
		// Range conditions.
		`2 BETWEEN 1 AND 3`,
		`1 NOT BETWEEN 2 AND 3`,
		`'foo' BETWEEN 'a' AND 'z'`,
		// Case operator.
		`CASE WHEN true THEN 1 END`,
		`CASE WHEN false THEN 1 END`,
		`CASE WHEN false THEN 1 ELSE 2 END`,
		`CASE WHEN false THEN 1 WHEN false THEN 2 END`,
		`CASE 1+1 WHEN 1 THEN 1 WHEN 2 THEN 2 END`,
		`CASE 1+2 WHEN 1 THEN 1 WHEN 2 THEN 2 ELSE 5 END`,
		// Row (tuple) comparisons.
		`ROW(1) = ROW(1)`,
		`ROW(1, true) = (1, NOT false)`,
		`(1, 'a') = (1, 'a')`,
		`(1, 'a' || 1::char) = (1, 'a1')`,
		`(1+1, (2+2, (3+3))) = (2, (4, (6)))`,
		`(1, 'a') != (1, 'a')`,
		`(1, 'a') != (1, 'b')`,
		// IN and NOT IN expressions.
		`1 NOT IN (2, 3, 4)`,
		`1+1 IN (2, 3, 4)`,
		`'a0' IN ('a'||0::char, 'b'||1::char, 'c'||2::char)`,
		`'2012-09-21'::date IN ('2012-09-21'::date)`,
		`'2010-09-28 12:00:00.1'::timestamp IN ('2010-09-28 12:00:00.1'::timestamp)`,
		`'34h'::interval IN ('34h'::interval)`,
		`(1,2) IN ((0+1,1+1), (3,4), (5,6))`,
		`(1, 2) IN ((2, 1), (3, 4))`,
		// Func expressions.
		`length('hel'||'lo')`,
		`lower('HELLO')`,
		`UPPER('hello')`,
		// Cast expressions.
		`true::boolean`,
		`true::int`,
		`true::float`,
		`length(true::text)`,
		`false::boolean`,
		`false::int`,
		`false::float`,
		`true::decimal`,
		`false::decimal`,
		`length(false::text)`,
		`1::boolean`,
		`0::boolean`,
		`1::int`,
		`1::float`,
		`1::decimal`,
		`length(123::text)`,
		`1.1::boolean`,
		`0.0::boolean`,
		`(1.1::decimal)::int`,
		`(1.9::decimal)::int`,
		`(1.1::decimal)::float`,
		`(1.1::decimal)::boolean`,
		`(0.0::decimal)::boolean`,
		`1.1::int`,
		`1.5::int`,
		`1.9::int`,
		`2.5::int`,
		`-1.5::int`,
		`-2.5::int`,
		`1.1::float`,
		`-1e+06`,
		`-9.99999e+05`,
		`999999.0`,
		`1000000.0`,
		`-1e+06::decimal`,
		`-9.99999e+05::decimal`,
		`999999.0::decimal`,
		`1000000.0::decimal`,
		`length(1.23::text)`,
		`'t'::boolean`,
		`'T'::boolean`,
		`'true'::boolean`,
		`'True'::boolean`,
		`'TRUE'::boolean`,
		`'1'::boolean`,
		`'f'::boolean`,
		`'F'::boolean`,
		`'false'::boolean`,
		`'False'::boolean`,
		`'FALSE'::boolean`,
		`'0'::boolean`,
		`'123'::int + 1`,
		`NULL::int`,
		`'0x123'::int + 1`,
		`'0123'::int + 1`,
		`'1.23'::float + 1.0`,
		`'hello'::text`,
		`CAST('123' AS int) + 1`,
		`CAST(NULL AS int)`,
		`'hello'::char(2)`,
		`'hello'::bytes`,
		`b'hello'::string`,
		`b'\xff'`,
		`123::text`,
		`'2010-09-28'::date`,
		`'2010-09-28'::timestamp`,
		`('2010-09-28 12:00:00.1'::timestamp)::date`,
		`'2010-09-28 12:00:00.1'::timestamp`,
		`'2010-09-28 12:00:00.1+02:00'::timestamp`,
		`'2010-09-28 12:00:00.1-07:00'::timestamp`,
		`('2010-09-28'::date)::timestamp`,
		`'12h2m1s23ms'::interval`,
		`1::interval`,
		`'2010-09-28'::date + 3`,
		`3 + '2010-09-28'::date`,
		`'2010-09-28'::date - 3`,
		`'2010-09-28'::date - '2010-10-21'::date`,
		`'2010-09-28 12:00:00.1-04:00'::timestamp + '12h2m'::interval`,
		`'12h2m'::interval + '2010-09-28 12:00:00.1-04:00'::timestamp`,
		`'2010-09-28 12:00:00.1-04:00'::timestamp - '12h2m'::interval`,
		`'2010-09-28 12:00:00.1-04:00'::timestamp - '2010-09-28 12:00:00.1+00:00'::timestamp`,
		`'12h2m1s23ms'::interval + '1h'::interval`,
		`'12h2m1s23ms'::interval - '1h'::interval`,
		`'1h'::interval - '12h2m1s23ms'::interval`,
		`3 * '1h2m'::interval * 3`,
		`'3h'::interval / 2`,
		// Conditional expressions.
		`IF(true, 1, 2/0)`,
		`IF(false, 1/0, 2)`,
		`IF(NULL, 1/0, 2)`,
		`NULLIF(1, 1)`,
		`NULLIF(1, 2)`,
		`NULLIF(2, 1)`,
		`IFNULL(1, 2/0)`,
		`IFNULL(NULL, 2)`,
		`IFNULL(1, NULL)`,
		`IFNULL(NULL, NULL)`,
		`COALESCE(1, 2, 3, 4/0)`,
		`COALESCE(NULL, 2, 3, 4/0)`,
		`COALESCE(NULL, NULL, NULL, 4)`,
		`COALESCE(NULL, NULL, NULL, NULL)`,
	}

	for _, exprStr := range testExprs {
		expr, err := ParseExprTraditional(exprStr)
		if err != nil {
			t.Fatalf("%s: %v", exprStr, err)
		}
		exprCopy := expr.DeepCopy()

		if !reflect.DeepEqual(expr, exprCopy) {
			t.Fatalf("`%s`: copy not equal: `%s`\n%#v\nvs.%#v\n", expr, exprCopy, expr, exprCopy)
		}

		fields := util.EqualPtrFields(reflect.ValueOf(expr), reflect.ValueOf(exprCopy), "")
		if len(fields) > 0 {
			t.Fatalf("equal pointer field(s) %s", strings.Join(fields, ","))
		}
	}
}