ClickHouse/ch-go

Default values are not triggered when inserting data???

wangxuanyue opened this issue · 4 comments

CREATE TABLE test_materialization
(
    key UInt32,
    value UInt32,
    inserted_at DateTime DEFAULT now()
)
ENGINE = MergeTree
ORDER BY key;

use ch-go insert key and value column

key value inserted_at
1 1 1970-01-01 00:00:00

use clickhouse-client key and value column

insert into test_materialization(key,value)values(2,2);
select * from test_materialization;
key value inserted_at
1 1 1970-01-01 00:00:00
2 2 2023-02-15 16:34:11

Are you sure that you are not inserting the inserted_at column?

I've made following test:

func TestClientInsertDefault(t *testing.T) {
	ctx := context.Background()
	conn := Conn(t)
	require.NoError(t, conn.Do(ctx, Query{
		Body: `CREATE TABLE test_table
(
    key UInt32,
    value UInt32,
    inserted_at DateTime DEFAULT now()
)
ENGINE = Memory`,
	}))

	{
		// Insert.
		// Generate 5 test rows.
		var (
			key   proto.ColUInt32
			value proto.ColUInt32
		)
		for i := 0; i < 5; i++ {
			key.Append(uint32(i))
			value.Append(uint32(i * 10))
		}
		require.NoError(t, conn.Do(ctx, Query{
			Body: "INSERT INTO test_table (key, value) VALUES",
			Input: proto.Input{
				{Name: "key", Data: key},
				{Name: "value", Data: value},
			},
		}))
	}
	{
		// Select.
		var (
			key        proto.ColUInt32
			value      proto.ColUInt32
			insertedAt proto.ColDateTime
		)
		require.NoError(t, conn.Do(ctx, Query{
			Body: "SELECT * FROM test_table",
			Result: proto.Results{
				{Name: "key", Data: &key},
				{Name: "value", Data: &value},
				{Name: "inserted_at", Data: &insertedAt},
			},
		}))

		for i := 0; i < key.Rows(); i++ {
			t.Logf("key=%d, value=%d, inserted_at=%s",
				key.Row(i),
				value.Row(i),
				insertedAt.Row(i),
			)
		}
	}
}

This test output:

    query_test.go:1435: key=0, value=0, inserted_at=2023-02-15 15:44:47 +0000 UTC
    query_test.go:1435: key=1, value=10, inserted_at=2023-02-15 15:44:47 +0000 UTC
    query_test.go:1435: key=2, value=20, inserted_at=2023-02-15 15:44:47 +0000 UTC
    query_test.go:1435: key=3, value=30, inserted_at=2023-02-15 15:44:47 +0000 UTC
    query_test.go:1435: key=4, value=40, inserted_at=2023-02-15 15:44:47 +0000 UTC

Yes,In my program, the fields to be inserted are dynamically generated according to the table structure.
Here is just an example:

	conn, err := ch.Dial(context.Background(), opt)
	if err != nil {
		log.Fatal(err)
	}

	var data proto.Input
	data = append(data, proto.InputColumn{Name: "key", Data: new(proto.ColUInt32)})
	data = append(data, proto.InputColumn{Name: "value", Data: new(proto.ColUInt32)})

	data[0].Data.(*proto.ColUInt32).Append(6)
	data[1].Data.(*proto.ColUInt32).Append(6)

	err = conn.Do(context.Background(), ch.Query{
		Body:  "INSERT INTO test_materialization values",
		Input: data,
	})
	if err != nil {
		log.Fatal(err)
	}

	{
		// Select.
		var (
			key        proto.ColUInt32
			value      proto.ColUInt32
			insertedAt proto.ColDateTime
		)
		err := conn.Do(context.Background(), ch.Query{
			Body: "SELECT * FROM test_materialization",
			Result: proto.Results{
				{Name: "key", Data: &key},
				{Name: "value", Data: &value},
				{Name: "inserted_at", Data: &insertedAt},
			},
			OnResult: func(ctx context.Context, block proto.Block) error {
				for i := 0; i < block.Rows; i++ {
					fmt.Printf("key=%d, value=%d, inserted_at=%s\n",
						key.Row(i),
						value.Row(i),
						insertedAt.Row(i),
					)
				}
				return nil
			},
		})
		if err != nil {
			log.Fatal(err)
		}
	}

This test output:

key=1, value=1, inserted_at=2023-02-15 14:59:16 +0800 CST
key=2, value=2, inserted_at=2023-02-15 14:59:16 +0800 CST
key=3, value=3, inserted_at=2023-02-15 14:56:13 +0800 CST
key=4, value=4, inserted_at=2023-02-15 15:02:29 +0800 CST
key=5, value=5, inserted_at=0001-01-01 08:05:43 +0805 LMT
key=6, value=6, inserted_at=0001-01-01 08:05:43 +0805 LMT

@wangxuanyue

Please try

	err = conn.Do(context.Background(), ch.Query{
		Body:  "INSERT INTO test_materialization (key, value) values",
		Input: data,
	})

Instead of

	err = conn.Do(context.Background(), ch.Query{
		Body:  "INSERT INTO test_materialization values",
		Input: data,
	})

I.e. explicitly provide names of columns you want to insert.

It works,thank you!

I thought the column to be inserted was auto-inferred