Connect to the specified SQL Server instance, returning a [`Client`] that can be used to query it and a [`Connection`] that must be polled to send and receive results. TODO(sql_server2): Maybe return a `ClientBuilder` here that implements IntoFuture and does the default good thing of moving the `Connection` into a tokio task? And a `.raw()` option that will instead return both the Client and Conn
(config: Config)
| 60 | /// into a tokio task? And a `.raw()` option that will instead return both |
| 61 | /// the Client and Connection for manual polling. |
| 62 | pub async fn connect(config: Config) -> Result<Self, SqlServerError> { |
| 63 | // Setup our tunnelling and return any resources that need to be kept |
| 64 | // alive for the duration of the connection. |
| 65 | let (tcp, resources): (_, Option<Box<dyn Any + Send + Sync>>) = match &config.tunnel { |
| 66 | TunnelConfig::Direct { resolved_addresses } => { |
| 67 | let tcp = if resolved_addresses.is_empty() { |
| 68 | TcpStream::connect(config.inner.get_addr()).await |
| 69 | } else { |
| 70 | TcpStream::connect(resolved_addresses.as_ref()).await |
| 71 | } |
| 72 | .context("direct")?; |
| 73 | (tcp, None) |
| 74 | } |
| 75 | TunnelConfig::Ssh { |
| 76 | config: ssh_config, |
| 77 | manager, |
| 78 | timeout, |
| 79 | host, |
| 80 | port, |
| 81 | } => { |
| 82 | // N.B. If this tunnel is dropped it will close so we need to |
| 83 | // keep it alive for the duration of the connection. |
| 84 | let tunnel = manager |
| 85 | .connect(ssh_config.clone(), host, *port, *timeout, config.in_task) |
| 86 | .await?; |
| 87 | let tcp = TcpStream::connect(tunnel.local_addr()) |
| 88 | .await |
| 89 | .context("ssh tunnel")?; |
| 90 | |
| 91 | (tcp, Some(Box::new(tunnel))) |
| 92 | } |
| 93 | TunnelConfig::AwsPrivatelink { |
| 94 | connection_id, |
| 95 | port, |
| 96 | } => { |
| 97 | let privatelink_host = mz_cloud_resources::vpc_endpoint_name(*connection_id); |
| 98 | let tcp = TcpStream::connect((privatelink_host.as_str(), *port)) |
| 99 | .await |
| 100 | .context(format!("aws privatelink {:?}", privatelink_host))?; |
| 101 | |
| 102 | (tcp, None) |
| 103 | } |
| 104 | }; |
| 105 | |
| 106 | tcp.set_nodelay(true)?; |
| 107 | |
| 108 | let (client, connection) = Self::connect_raw(config, tcp, resources).await?; |
| 109 | mz_ore::task::spawn(|| "sql-server-client-connection", async move { |
| 110 | connection.await |
| 111 | }); |
| 112 | |
| 113 | Ok(client) |
| 114 | } |
| 115 | |
| 116 | /// Create a new Client instance with the same configuration that created |
| 117 | /// this configuration. |
no test coverage detected