转_phpcan't return a result set in the given context及参数解释

本文介绍了如何使用PHP处理MySQL多结果集,详细解释了CLIENT_MULTI_RESULTS标志的作用,并提供了示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


关键就是两点
 

define('CLIENT_MULTI_RESULTS', 131072);
 
$link= mysql_connect("127.0.0.1","root","",1,CLIENT_MULTI_RESULTS) or die("Could not connect: ".mysql_error());


下面就可以正常使用了,以下是例子程序。

 

 1 <?php
 2 define('CLIENT_MULTI_RESULTS', 131072);
 3
 4 $link=mysql_connect("127.0.0.1","root","",1,CLIENT_MULTI_RESULTS)ordie("Could not connect: ".mysql_error());
 5 mysql_select_db("vs")ordie("Could not select database");
 6 ?>
 7
 8 <?php
 9 $result=mysql_query("call get_news_from_class_id(2)")ordie("Query failed:".mysql_error());
10 while($row=mysql_fetch_array($result,MYSQL_ASSOC))
11 {
12 $line='<tr><td><a target = _blank href=\''.$row["url"].'\'>'.$row["title"].'('.$row["page_time"].')'.'</a></td></tr>';
14 echo$line;
15 printf(" ");
16
17 }
18 mysql_free_result($result);
19 ?>
20
21 <?php
22 mysql_close($link);
23 ?>
   其中的一个参数CLIENT_MULTI_RESULTS不明白是什么意思,google之,在mysql的官方主页上关于mysql提供的c接口的文档(http://dev.mysql.com/doc/refman/5.0/en/mysql-real-connect.html)里找到了这个参数和其他一些参数,我大概翻译了一下描述,如下:
Flag Name    Flag Description
CLIENT_COMPRESS    Use compression protocol.(使用压缩协议。)
CLIENT_FOUND_ROWS    Return the number of found (matched) rows, not the number of changed rows.(返回找到(匹配)的行数,而不是改变了的行数。)
CLIENT_IGNORE_SIGPIPE    Prevents the client library from installing a SIGPIPE signal handler. This can be used to avoid conflicts with a handler that the application has already installed.(阻止客户端库安装一个SIGPIPE信号处理器。这个可以用于当应用程序已经安装该处理器的时候避免与其发生冲突。)
CLIENT_IGNORE_SPACE    Allow spaces after function names. Makes all functions names reserved words.(允许在函数名后使用空格。所有函数名可以预留字。)
CLIENT_INTERACTIVE    Allow interactive_timeout seconds (instead of wait_timeout seconds) of inactivity before closing the connection. The client's session wait_timeout variable is set to the value of the session interactive_timeout variable.(允许使用关闭连接之前的不活动交互超时的描述,而不是等待超时秒数。客户端的会话等待超时变量变为交互超时变量。)
CLIENT_LOCAL_FILES    Enable LOAD DATA LOCAL handling.
CLIENT_MULTI_RESULTS    Tell the server that the client can handle multiple result sets from multiple-statement executions or stored procedures. This flag is automatically enabled if CLIENT_MULTI_STATEMENTS is enabled. See the note following this table for more information about this flag.(通知服务器客户端可以处理由多语句或者存储过程执行生成的多结果集。当打开CLIENT_MULTI_STATEMENTS时,这个标志自动的被打开。可以在本表后查看更多关于该标志位的信息。)
CLIENT_MULTI_STATEMENTS    Tell the server that the client may send multiple statements in a single string (separated by “;”). If this flag is not set, multiple-statement execution is disabled. See the note following this table for more information about this flag.(通知服务器客户端可以发送多条语句(由分号分隔)。如果该标志为没有被设置,多条语句执行。)
CLIENT_NO_SCHEMA    Don't allow the db_name.tbl_name.col_name syntax. This is for ODBC. It causes the parser to generate an error if you use that syntax, which is useful for trapping bugs in some ODBC programs.(不允许“数据库名.表名.列名”这样的语法。这是对于ODBC的设置。当使用这样的语法时解析器会产生一个错误,这对于一些ODBC的程序限制bug来说是有用的。)
CLIENT_ODBC    Unused.(不使用)
CLIENT_SSL    Use SSL (encrypted protocol). This option should not be set by application programs; it is set internally in the client library. Instead, use mysql_ssl_set() before calling mysql_real_connect().(使用SSL。这个设置不应该被应用程序设置,他应该是在客户端库内部是设置的。可以在调用mysql_real_connect()之前调用mysql_ssl_set()来代替设置。)
CLIENT_REMEMBER_OPTIONS    Remember options specified by calls to mysql_options(). Without this option, if mysql_real_connect() fails, you must repeat the mysql_options() calls before trying to connect again. With this option, the mysql_options() calls need not be repeated.(记住通过调用mysql_options()生成的设置。如果不使用这个设置,当mysql_real_connect失败时,再重新连接之前必须反复调用mysql_options()。当然,如果使用这个设置,就不必反复调用了。)

    下面有对于CLIENT_MULTI_STATEMENTS的说明:
If you enable CLIENT_MULTI_STATEMENTS or CLIENT_MULTI_RESULTS, you should process the result for every call to mysql_query() or mysql_real_query() by using a loop that calls mysql_next_result() to determine whether there are more results. For an example, see Section 20.9.12, “C API Support for Multiple Statement Execution”.

如果打开了CLIENT_MULTI_STATEMENTS或CLIENT_MULTI_RESULTS,你必须对每一个mysql_query()或者mysql_real_query()的调用结果通过一个循环来处理,在这个循环中,调用mysql_next_result()来决定(发现)是否有更多的结果,如Section 20.9.12, “C API Support for Multiple Statement Execution”

impl VirtioDevice for VhostUserFrontend { // Override the default debug label to differentiate vhost-user devices from virtio. fn debug_label(&self) -> String { format!("vu-{}", self.device_type()) } fn keep_rds(&self) -> Vec<RawDescriptor> { Vec::new() } fn device_type(&self) -> DeviceType { self.device_type } fn queue_max_sizes(&self) -> &[u16] { &self.queue_sizes } fn features(&self) -> u64 { self.avail_features } fn ack_features(&mut self, features: u64) { let features = (features & self.avail_features) | self.acked_features; if let Err(e) = self .backend_client .lock() .set_features(features) .map_err(Error::SetFeatures) { error!("failed to enable features 0x{:x}: {}", features, e); return; } self.acked_features = features; } fn read_config(&self, offset: u64, data: &mut [u8]) { if let Some(cfg) = &self.cfg { copy_config(data, 0, cfg, offset); return; } let Ok(offset) = offset.try_into() else { error!("failed to read config: invalid config offset is given: {offset}"); return; }; let Ok(data_len) = data.len().try_into() else { error!( "failed to read config: invalid config length is given: {}", data.len() ); return; }; let (_, config) = match self.backend_client.lock().get_config( offset, data_len, VhostUserConfigFlags::WRITABLE, data, ) { Ok(x) => x, Err(e) => { error!("failed to read config: {}", Error::GetConfig(e)); return; } }; data.copy_from_slice(&config); } fn write_config(&mut self, offset: u64, data: &[u8]) { let Ok(offset) = offset.try_into() else { error!("failed to write config: invalid config offset is given: {offset}"); return; }; if let Err(e) = self .backend_client .lock() .set_config(offset, VhostUserConfigFlags::empty(), data) .map_err(Error::SetConfig) { error!("failed to write config: {}", e); } } fn activate( &mut self, mem: GuestMemory, interrupt: Interrupt, queues: BTreeMap<usize, Queue>, ) -> anyhow::Result<()> { self.set_mem_table(&mem)?; let msix_config_opt = interrupt .get_msix_config() .as_ref() .ok_or(Error::MsixConfigUnavailable)?; let msix_config = msix_config_opt.lock(); let non_msix_evt = Event::new().map_err(Error::CreateEvent)?; for (&queue_index, queue) in queues.iter() { let irqfd = msix_config .get_irqfd(queue.vector() as usize) .unwrap_or(&non_msix_evt); self.activate_vring(&mem, queue_index, queue, irqfd)?; } self.sent_queues = Some(queues); drop(msix_config); self.start_worker(interrupt, non_msix_evt); Ok(()) } fn reset(&mut self) -> anyhow::Result<()> { if let Some(sent_queues) = self.sent_queues.take() { for queue_index in sent_queues.into_keys() { let _vring_base = self .deactivate_vring(queue_index) .context("deactivate_vring failed during reset")?; } } if let Some(w) = self.worker_thread.take() { self.backend_req_handler = w.stop(); } Ok(()) } fn pci_address(&self) -> Option<PciAddress> { self.pci_address } fn get_shared_memory_region(&self) -> Option<SharedMemoryRegion> { if !self .protocol_features .contains(VhostUserProtocolFeatures::SHARED_MEMORY_REGIONS) { return None; } if let Some(r) = self.shmem_region.borrow().as_ref() { return r.clone(); } let regions = match self .backend_client .lock() .get_shared_memory_regions() .map_err(Error::ShmemRegions) { Ok(x) => x, Err(e) => { error!("Failed to get shared memory regions {}", e); return None; } }; let region = match regions.len() { 0 => None, 1 => Some(SharedMemoryRegion { id: regions[0].id, length: regions[0].length, }), n => { error!( "Failed to get shared memory regions {}", Error::TooManyShmemRegions(n) ); return None; } }; *self.shmem_region.borrow_mut() = Some(region.clone()); region } fn set_shared_memory_mapper(&mut self, mapper: Box<dyn SharedMemoryMapper>) { // Return error if backend request handler is not available. This indicates // that `VhostUserProtocolFeatures::BACKEND_REQ` is not negotiated. let Some(backend_req_handler) = self.backend_req_handler.as_mut() else { error!( "Error setting shared memory mapper {}", Error::ProtocolFeatureNotNegoiated(VhostUserProtocolFeatures::BACKEND_REQ) ); return; }; // The virtio framework will only call this if get_shared_memory_region returned a region let shmid = self .shmem_region .borrow() .clone() .flatten() .expect("missing shmid") .id; backend_req_handler .frontend_mut() .set_shared_mapper_state(mapper, shmid); } fn expose_shmem_descriptors_with_viommu(&self) -> bool { self.expose_shmem_descriptors_with_viommu } fn virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>> { let Some(mut queues) = self.sent_queues.take() else { return Ok(None); }; for (&queue_index, queue) in queues.iter_mut() { let vring_base = self .deactivate_vring(queue_index) .context("deactivate_vring failed during sleep")?; queue.vhost_user_reclaim(vring_base); } if let Some(w) = self.worker_thread.take() { self.backend_req_handler = w.stop(); } Ok(Some(queues)) } fn virtio_wake( &mut self, // Vhost user doesn't need to pass queue_states back to the device process, since it will // already have it. queues_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>, ) -> anyhow::Result<()> { if let Some((mem, interrupt, queues)) = queues_state { self.activate(mem, interrupt, queues)?; } Ok(()) } fn virtio_snapshot(&mut self) -> anyhow::Result<AnySnapshot> { if !self .protocol_features .contains(VhostUserProtocolFeatures::DEVICE_STATE) { bail!("snapshot requires VHOST_USER_PROTOCOL_F_DEVICE_STATE"); } let backend_client = self.backend_client.lock(); // Send the backend an FD to write the device state to. If it gives us an FD back, then // we need to read from that instead. let (mut r, w) = new_pipe_pair()?; let backend_r = backend_client .set_device_state_fd( VhostUserTransferDirection::Save, VhostUserMigrationPhase::Stopped, &w, ) .context("failed to negotiate device state fd")?; // EOF signals end of the device state bytes, so it is important to close our copy of // the write FD before we start reading. std::mem::drop(w); // Read the device state. let mut snapshot_bytes = Vec::new(); if let Some(mut backend_r) = backend_r { backend_r.read_to_end(&mut snapshot_bytes) } else { r.read_to_end(&mut snapshot_bytes) } .context("failed to read device state")?; // Call `check_device_state` to ensure the data transfer was successful. backend_client .check_device_state() .context("failed to transfer device state")?; Ok(AnySnapshot::to_any(snapshot_bytes).map_err(Error::SliceToSerdeValue)?) } fn virtio_restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> { if !self .protocol_features .contains(VhostUserProtocolFeatures::DEVICE_STATE) { bail!("restore requires VHOST_USER_PROTOCOL_F_DEVICE_STATE"); } let backend_client = self.backend_client.lock(); let data_bytes: Vec<u8> = AnySnapshot::from_any(data).map_err(Error::SerdeValueToSlice)?; // Send the backend an FD to read the device state from. If it gives us an FD back, // then we need to write to that instead. let (r, w) = new_pipe_pair()?; let backend_w = backend_client .set_device_state_fd( VhostUserTransferDirection::Load, VhostUserMigrationPhase::Stopped, &r, ) .context("failed to negotiate device state fd")?; // Write the device state. { // EOF signals the end of the device state bytes, so we need to ensure the write // objects are dropped before the `check_device_state` call. Done here by moving // them into this scope. let backend_w = backend_w; let mut w = w; if let Some(mut backend_w) = backend_w { backend_w.write_all(data_bytes.as_slice()) } else { w.write_all(data_bytes.as_slice()) } .context("failed to write device state")?; } // Call `check_device_state` to ensure the data transfer was successful. backend_client .check_device_state() .context("failed to transfer device state")?; Ok(()) } }
最新发布
05-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值