Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,4 @@ This library includes enhanced support for GaussDB and openGauss databases:
asyncio.run(run())

async-gaussdb is developed and distributed under the Apache 2.0 license
by MagicStack Inc. and the HuaweiCloudDeveloper team.
by MagicStack Inc. and the HuaweiCloudDeveloper team.
2 changes: 1 addition & 1 deletion async_gaussdb/gaussdbproto/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def from_int(cls: typing.Type[_BitString], x: int, length: int,
def __repr__(self) -> str:
return '<BitString {}>'.format(self.as_string())

__str__: typing.Callable[['BitString'], str] = __repr__
__str__ = __repr__

def __eq__(self, other: object) -> bool:
if not isinstance(other, BitString):
Expand Down
95 changes: 95 additions & 0 deletions examples/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@

import asyncio
import async_gaussdb
# -----------------------------------------------------------------------------
# Database Connection Configuration
# -----------------------------------------------------------------------------
DB_CONFIG = {
'user': 'root',
'password': 'password', # Replace with your actual password
'database': 'postgres',
'host': '127.0.0.1',
'port': 8000
}

async def main():
print(f"Connecting to GaussDB at {DB_CONFIG['host']}:{DB_CONFIG['port']}...")

# 1. Establish Connection
# async_gaussdb automatically handles openGauss/GaussDB specific protocols (e.g., SHA256 auth)
conn = await async_gaussdb.connect(**DB_CONFIG)
print("✅ Connection established successfully!")

try:
# ---------------------------------------------------------------------
# Step 1: Clean up old data (Drop Table)
# ---------------------------------------------------------------------
drop_table_sql = "DROP TABLE IF EXISTS test"
print(f"\n[Executing] {drop_table_sql}")
await conn.execute(drop_table_sql)
print(" -> Table 'test' dropped.")

# ---------------------------------------------------------------------
# Step 2: Create new table (Create Table)
# ---------------------------------------------------------------------
create_table_sql = (
"CREATE TABLE test (id serial PRIMARY KEY, num integer, data text)"
)
print(f"\n[Executing] {create_table_sql}")
await conn.execute(create_table_sql)
print(" -> Table 'test' created.")

# ---------------------------------------------------------------------
# Step 3: Insert Data
# Note: Async drivers for Postgres/GaussDB typically use $1, $2 placeholders
# instead of %s used in standard synchronous drivers.
# ---------------------------------------------------------------------
insert_data_sql = "INSERT INTO test (num, data) VALUES ($1, $2)"

# Preparing sample data
data_to_insert = [
(1, 'initial_data'),
(2, 'data_to_be_updated'), # This row (num=2) will be updated later
(3, 'other_data')
]

print(f"\n[Executing] {insert_data_sql}")
for num, data in data_to_insert:
await conn.execute(insert_data_sql, num, data)
print(f" -> Inserted row: num={num}, data='{data}'")

# ---------------------------------------------------------------------
# Step 4: Update Data
# ---------------------------------------------------------------------
update_data_sql = "UPDATE test SET data = 'gaussdb' WHERE num = 2"
print(f"\n[Executing] {update_data_sql}")
result = await conn.execute(update_data_sql)
# 'result' usually contains the command tag (e.g., "UPDATE 1")
print(f" -> Update complete: {result}")

# ---------------------------------------------------------------------
# Step 5: Select and Verify Data
# ---------------------------------------------------------------------
select_sql = "SELECT * FROM test ORDER BY id"
print(f"\n[Executing] {select_sql}")

# fetch() returns a list of Record objects
rows = await conn.fetch(select_sql)

print("\n--- Query Results ---")
for row in rows:
# Access data by column name or index
print(f"ID: {row['id']} | Num: {row['num']} | Data: {row['data']}")

except Exception as e:
print(f"\n❌ An error occurred: {e}")
finally:
# ---------------------------------------------------------------------
# Close Connection
# ---------------------------------------------------------------------
print("\nClosing connection...")
await conn.close()
print("✅ Connection closed.")

if __name__ == "__main__":
asyncio.run(main())
99 changes: 99 additions & 0 deletions examples/ssl_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@

import asyncio
import async_gaussdb
import os

# -----------------------------------------------------------------------------
# Scenario: Configuring SSL using DSN (Data Source Name)
# This method is simpler than creating a raw ssl.SSLContext and mimics
# standard PostgreSQL connection strings.
# -----------------------------------------------------------------------------

# Path to your server's CA certificate.
# If 'sslrootcert' is not provided, the driver defaults to looking at:
# ~/.postgresql/root.crt (Linux/Mac) or %APPDATA%\postgresql\root.crt (Windows)
CERTS = os.path.join(os.path.dirname(__file__), '../tests/certs')
SSL_CERT_FILE = os.path.join(CERTS, 'server.cert.pem')
async def main():
# -------------------------------------------------------------------------
# Constructing the DSN Connection String
# Format: gaussdb://user:password@host:port/database?param=value
#
# Key Parameters:
# 1. sslmode=verify-ca -> Verifies the server's certificate signature.
# (Use 'verify-full' to also verify the hostname)
# 2. sslrootcert=... -> Explicitly tells the driver where the CA file is.
# -------------------------------------------------------------------------

dsn = (
f"gaussdb://testuser:Test%40123@127.0.0.1:5432/postgres"
f"?sslmode=verify-ca&sslrootcert={SSL_CERT_FILE}"
)

print(f"Connecting via DSN: ...sslmode=verify-ca&sslrootcert={os.path.basename(SSL_CERT_FILE)}")

try:
# Connect to the database
# We do not need to pass a 'ssl=' context object here because the DSN
# contains all the necessary configuration.
conn = await async_gaussdb.connect(dsn)

print("SSL Connection Successful (via sslmode)!")
print(f" Encryption Status: {conn._protocol.is_ssl}")

# ---------------------------------------------------------------------
# Core Tasks (Drop -> Create -> Insert -> Update -> Select)
# ---------------------------------------------------------------------

# 1. Clean up old data
drop_table_sql = "DROP TABLE IF EXISTS test"
print(f"\n[Executing] {drop_table_sql}")
await conn.execute(drop_table_sql)

# 2. Create new table
create_table_sql = (
"CREATE TABLE test (id serial PRIMARY KEY, num integer, data text)"
)
print(f"\n[Executing] {create_table_sql}")
await conn.execute(create_table_sql)

# 3. Insert Data (Using $1, $2 placeholders for async driver)
insert_data_sql = "INSERT INTO test (num, data) VALUES ($1, $2)"
print(f"\n[Executing] {insert_data_sql}")

await conn.execute(insert_data_sql, 1, "sslmode_demo")
await conn.execute(insert_data_sql, 2, "wait_for_update") # num=2 will be updated
print(" -> Inserted 2 rows.")

# 4. Update Data
update_data_sql = "UPDATE test SET data = 'gaussdb' WHERE num = 2"
print(f"\n[Executing] {update_data_sql}")
await conn.execute(update_data_sql)
print(" -> Update complete.")

# 5. Select and Verify
select_sql = "SELECT * FROM test ORDER BY id"
print(f"\n[Executing] {select_sql}")
rows = await conn.fetch(select_sql)

print("\n--- Query Results ---")
for row in rows:
print(f"ID: {row['id']} | Num: {row['num']} | Data: {row['data']}")

except Exception as e:
print(f"\nERROR Connection or Execution Failed: {e}")
print(" Hint: Check if 'server.crt' exists and if the server supports SSL.")

finally:
if 'conn' in locals():
print("\nClosing connection...")
await conn.close()
print("✅ Connection closed.")

if __name__ == "__main__":
# Check for file existence just for this tutorial to be helpful
if not os.path.exists(SSL_CERT_FILE):
print(f"⚠️ WARNING: The certificate file was not found at: {SSL_CERT_FILE}")
print(" (The code will attempt to connect, but will likely fail)")

asyncio.run(main())
8 changes: 4 additions & 4 deletions tests/test_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,14 +721,14 @@ async def test_pool_max_inactive_time_05(self):
# the max inactive lifetime.
async with self.create_pool(
database='postgres', min_size=2, max_size=2,
max_inactive_connection_lifetime=0.3) as pool:
max_inactive_connection_lifetime=0.5) as pool:

await asyncio.sleep(0.02)
await asyncio.sleep(0.1)
self.assertIsNotNone(pool._holders[0]._con)
self.assertIsNotNone(pool._holders[1]._con)

await pool.execute('SELECT pg_sleep(0.3)')
await asyncio.sleep(0.3)
await pool.execute('SELECT pg_sleep(0.5)')
await asyncio.sleep(0.5)

self.assertIs(pool._holders[0]._con, None)
# The connection in the second holder was never used,
Expand Down