Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client,mysql: Add support for Query Attributes #976

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

dveeden
Copy link
Collaborator

@dveeden dveeden commented Jan 27, 2025

Just like connection attributes, there are also query attributes in MySQL. These allow one to pass key/value pairs along with queries.

These can be used to add metadata about:

In some other languages, etc:

MySQL Client

mysql-9.2.0> query_attributes proxy_user myuser page index.html
mysql-9.2.0> SELECT mysql_query_attribute_string('proxy_user'), mysql_query_attribute_string('page');
+--------------------------------------------+--------------------------------------+
| mysql_query_attribute_string('proxy_user') | mysql_query_attribute_string('page') |
+--------------------------------------------+--------------------------------------+
| myuser                                     | index.html                           |
+--------------------------------------------+--------------------------------------+
1 row in set (0.00 sec)

MySQL Connector/Python

#!/bin/python3
import mysql.connector

c = mysql.connector.connect(host='127.0.0.1',user='root', ssl_disabled=True)

cur = c.cursor(prepared=True)
cur.add_attribute("proxy_user", "myuser")
cur.execute("SELECT ?, mysql_query_attribute_string('proxy_user')", ("hello",))
for row in cur:
    print(row)
cur.close()
c.close()

Output:

('hello', 'myuser')

go-mysql with this PR

package main

import (
	"fmt"

	"github.com/go-mysql-org/go-mysql/client"
	"github.com/go-mysql-org/go-mysql/mysql"
)

func main() {
	conn, err := client.Connect("127.0.0.1:3306", "root", "", "")
	if err != nil {
		panic(err)
	}
	defer conn.Quit()

	proxyAttr := mysql.QueryAttribute{
		Name:  "proxy_user",
		Value: "user1",
	}
	secondAttr := mysql.QueryAttribute{
		Name:  "attr2",
		Value: "value2",
	}
	conn.SetQueryAttributes(proxyAttr, secondAttr)

	fmt.Printf("Sending COM_QUERY \"SELECT mysql_query_attribute_string('proxy_user')\" with attributes: %v, %v\n", proxyAttr, secondAttr)
	r, err := conn.Execute("SELECT mysql_query_attribute_string('proxy_user')")
	if err != nil {
		panic(err)
	}
	defer r.Close()

	for _, row := range r.Values {
		if len(row) != 1 {
			panic("expecting exactly on column")
		}
		fmt.Printf("%s\n", row[0].Value())
	}

	fmt.Printf("Preparing 'SELECT mysql_query_attribute_string(?)' via COM_STMT_PREPARE\n")
	stmt, err := conn.Prepare("SELECT mysql_query_attribute_string(?)")
	if err != nil {
		panic(err)
	}
	defer stmt.Close()

	conn.SetQueryAttributes(proxyAttr)
	fmt.Printf("Sending COM_STMT_EXECUTE with arg: %s, attributes: %v\n", "proxy_user", proxyAttr)
	res, err := stmt.Execute("proxy_user")
	if err != nil {
		panic(err)
	}
	defer res.Close()
	for _, row := range res.Values {
		if len(row) != 1 {
			panic("expecting exactly on column")
		}
		fmt.Printf("%s\n", row[0].Value())
	}
}

Output:

Sending COM_QUERY "SELECT mysql_query_attribute_string('proxy_user')" with attributes: {proxy_user user1}, {attr2 value2}
user1
Preparing 'SELECT mysql_query_attribute_string(?)' via COM_STMT_PREPARE
Sending COM_STMT_EXECUTE with arg: proxy_user, attributes: {proxy_user user1}
user1

@dveeden
Copy link
Collaborator Author

dveeden commented Jan 27, 2025

@lance6716 @atercattus this works and is ready for review. However this needs some unit tests etc and more manual testing before it can be merged. Should I add a DNM flag in the title? Add a "hold" flag? Or change the status to draft?

@dveeden
Copy link
Collaborator Author

dveeden commented Jan 27, 2025

This is how this looks in Wireshark:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant