@@ -1541,6 +1541,257 @@ pub extern "C" fn rorm_row_free(_: Box<Row>) {}
1541
1541
// INSERT
1542
1542
// --------
1543
1543
1544
+ /**
1545
+ This functions inserts a row into the database while returning the requested columns.
1546
+
1547
+ **Parameter**:
1548
+ - `db`: Reference tot he Database, provided by [rorm_db_connect]
1549
+ - `transaction`: Mutable pointer to a Transaction. Can be a null pointer to ignore this parameter.
1550
+ - `model`: Name of the table to query.
1551
+ - `columns`: Array of columns to insert to the table.
1552
+ - `row`: List of values to insert. Must be of the same length as `columns`.
1553
+ - `returning`: Array of column to return after for the insert operation.
1554
+ - `callback`: callback function. Takes the `context` a pointer to a row and an [Error].
1555
+ - `context`: Pass through void pointer.
1556
+
1557
+ **Important**:
1558
+ - Make sure that `db`, `model`, `columns`, `row` and `returning` are allocated until the callback is executed.
1559
+ - The Row that is returned in the callback is freed after the callback has ended.
1560
+
1561
+ This function is called from an asynchronous context.
1562
+ */
1563
+ #[ no_mangle]
1564
+ pub extern "C" fn rorm_db_insert_returning (
1565
+ db : & ' static Database ,
1566
+ transaction : Option < & ' static mut Transaction > ,
1567
+ model : FFIString < ' static > ,
1568
+ columns : FFISlice < ' static , FFIString < ' static > > ,
1569
+ row : FFISlice < ' static , FFIValue < ' static > > ,
1570
+ returning : FFISlice < ' static , FFIString < ' static > > ,
1571
+ callback : Option < unsafe extern "C" fn ( VoidPtr , Option < Box < Row > > , Error ) -> ( ) > ,
1572
+ context : VoidPtr ,
1573
+ ) {
1574
+ let cb = callback. expect ( "Callback must not be empty" ) ;
1575
+
1576
+ let Ok ( model) = model. try_into ( ) else {
1577
+ unsafe { cb ( context, None , Error :: InvalidStringError ) } ;
1578
+ return ;
1579
+ } ;
1580
+
1581
+ let mut column_vec = vec ! [ ] ;
1582
+ {
1583
+ let column_slice: & [ FFIString ] = columns. into ( ) ;
1584
+ for & x in column_slice {
1585
+ let Ok ( v) = x. try_into ( ) else {
1586
+ unsafe { cb ( context, None , Error :: InvalidStringError ) } ;
1587
+ return ;
1588
+ } ;
1589
+ column_vec. push ( v) ;
1590
+ }
1591
+ }
1592
+
1593
+ let mut value_vec = vec ! [ ] ;
1594
+ {
1595
+ let value_slice: & [ FFIValue ] = row. into ( ) ;
1596
+ for x in value_slice {
1597
+ let x_conv = x. try_into ( ) ;
1598
+ if x_conv. is_err ( ) {
1599
+ match x_conv. as_ref ( ) . err ( ) . unwrap ( ) {
1600
+ Error :: InvalidStringError
1601
+ | Error :: InvalidDateError
1602
+ | Error :: InvalidTimeError
1603
+ | Error :: InvalidDateTimeError => unsafe {
1604
+ cb ( context, None , x_conv. err ( ) . unwrap ( ) )
1605
+ } ,
1606
+ _ => { }
1607
+ }
1608
+ return ;
1609
+ }
1610
+ value_vec. push ( x_conv. unwrap ( ) ) ;
1611
+ }
1612
+ }
1613
+
1614
+ let mut returning_vec = vec ! [ ] ;
1615
+ {
1616
+ let returning_slice: & [ FFIString ] = returning. into ( ) ;
1617
+ for x in returning_slice {
1618
+ let Ok ( v) = x. try_into ( ) else {
1619
+ unsafe { cb ( context, None , Error :: InvalidStringError ) } ;
1620
+ return ;
1621
+ } ;
1622
+ returning_vec. push ( v) ;
1623
+ }
1624
+ }
1625
+
1626
+ let fut = async move {
1627
+ match db
1628
+ . insert_returning (
1629
+ model,
1630
+ column_vec. as_slice ( ) ,
1631
+ value_vec. as_slice ( ) ,
1632
+ transaction,
1633
+ returning_vec. as_slice ( ) ,
1634
+ )
1635
+ . await
1636
+ {
1637
+ Err ( err) => unsafe {
1638
+ cb (
1639
+ context,
1640
+ None ,
1641
+ Error :: DatabaseError ( err. to_string ( ) . as_str ( ) . into ( ) ) ,
1642
+ )
1643
+ } ,
1644
+ Ok ( v) => unsafe { cb ( context, Some ( Box :: new ( v) ) , Error :: NoError ) } ,
1645
+ } ;
1646
+ } ;
1647
+
1648
+ let f = |err : String | {
1649
+ unsafe { cb ( context, None , Error :: RuntimeError ( err. as_str ( ) . into ( ) ) ) } ;
1650
+ } ;
1651
+ spawn_fut ! ( fut, cb( context, None , Error :: MissingRuntimeError ) , f) ;
1652
+ }
1653
+
1654
+ /**
1655
+ This function inserts multiple rows into the database while returning the requested columns from all
1656
+ inserted values.
1657
+
1658
+ **Parameter**:
1659
+ - `db`: Reference to the Database, provided by [rorm_db_connect].
1660
+ - `transaction`: Mutable pointer to a Transaction. Can be a null pointer to ignore this parameter.
1661
+ - `model`: Name of the table to query.
1662
+ - `columns`: Array of columns to insert to the table.
1663
+ - `rows`: List of list of values to insert. The inner lists must be of the same length as `columns`.
1664
+ - `returning`: Array of column to return after for the insert operation.
1665
+ - `callback`: callback function. Takes the `context` and an [Error].
1666
+ - `context`: Pass through void pointer.
1667
+
1668
+ **Important**:
1669
+ - Make sure that `db`, `model`, `columns`, `rows` and `returning` are allocated until the callback is executed.
1670
+ - The FFISlice returned in the callback is freed after the callback has ended.
1671
+
1672
+ This function is called from an asynchronous context.
1673
+ */
1674
+ #[ no_mangle]
1675
+ pub extern "C" fn rorm_db_insert_bulk_returning (
1676
+ db : & ' static Database ,
1677
+ transaction : Option < & ' static mut Transaction > ,
1678
+ model : FFIString < ' static > ,
1679
+ columns : FFISlice < ' static , FFIString < ' static > > ,
1680
+ rows : FFISlice < ' static , FFISlice < ' static , FFIValue < ' static > > > ,
1681
+ returning : FFISlice < ' static , FFIString < ' static > > ,
1682
+ callback : Option < unsafe extern "C" fn ( VoidPtr , FFISlice < & Row > , Error ) -> ( ) > ,
1683
+ context : VoidPtr ,
1684
+ ) {
1685
+ let cb = callback. expect ( "Callback must not be empty" ) ;
1686
+
1687
+ let model_conv = model. try_into ( ) ;
1688
+ if model_conv. is_err ( ) {
1689
+ unsafe { cb ( context, FFISlice :: empty ( ) , Error :: InvalidStringError ) } ;
1690
+ return ;
1691
+ }
1692
+ let model = model_conv. unwrap ( ) ;
1693
+
1694
+ let mut column_vec = vec ! [ ] ;
1695
+ {
1696
+ let column_slice: & [ FFIString ] = columns. into ( ) ;
1697
+ for & x in column_slice {
1698
+ let x_conv = x. try_into ( ) ;
1699
+ if x_conv. is_err ( ) {
1700
+ unsafe { cb ( context, FFISlice :: empty ( ) , Error :: InvalidStringError ) } ;
1701
+ return ;
1702
+ }
1703
+ column_vec. push ( x_conv. unwrap ( ) ) ;
1704
+ }
1705
+ }
1706
+
1707
+ let mut rows_vec = vec ! [ ] ;
1708
+ {
1709
+ let row_slices: & [ FFISlice < FFIValue > ] = rows. into ( ) ;
1710
+ for row in row_slices {
1711
+ let mut row_vec = vec ! [ ] ;
1712
+ let row_slice: & [ FFIValue ] = row. into ( ) ;
1713
+ for x in row_slice {
1714
+ let val = x. try_into ( ) ;
1715
+ if val. is_err ( ) {
1716
+ match val. as_ref ( ) . err ( ) . unwrap ( ) {
1717
+ Error :: InvalidStringError
1718
+ | Error :: InvalidDateError
1719
+ | Error :: InvalidTimeError
1720
+ | Error :: InvalidDateTimeError => unsafe {
1721
+ cb ( context, FFISlice :: empty ( ) , val. err ( ) . unwrap ( ) )
1722
+ } ,
1723
+ _ => { }
1724
+ }
1725
+ return ;
1726
+ }
1727
+ row_vec. push ( val. unwrap ( ) ) ;
1728
+ }
1729
+ rows_vec. push ( row_vec) ;
1730
+ }
1731
+ }
1732
+
1733
+ let mut returning_vec = vec ! [ ] ;
1734
+ {
1735
+ let returning_slice: & [ FFIString ] = returning. into ( ) ;
1736
+ for x in returning_slice {
1737
+ let Ok ( v) = x. try_into ( ) else {
1738
+ unsafe { cb ( context, FFISlice :: empty ( ) , Error :: InvalidStringError ) }
1739
+ return ;
1740
+ } ;
1741
+
1742
+ returning_vec. push ( v) ;
1743
+ }
1744
+ }
1745
+
1746
+ let fut = async move {
1747
+ match db
1748
+ . insert_bulk_returning (
1749
+ model,
1750
+ column_vec. as_slice ( ) ,
1751
+ rows_vec
1752
+ . iter ( )
1753
+ . map ( |x| x. as_slice ( ) )
1754
+ . collect :: < Vec < & [ Value ] > > ( )
1755
+ . as_slice ( ) ,
1756
+ transaction,
1757
+ returning_vec. as_slice ( ) ,
1758
+ )
1759
+ . await
1760
+ {
1761
+ Ok ( v) => {
1762
+ let rows: Vec < & Row > = v. iter ( ) . collect ( ) ;
1763
+ let slice = rows. as_slice ( ) . into ( ) ;
1764
+ unsafe { cb ( context, slice, Error :: NoError ) }
1765
+ }
1766
+ Err ( err) => {
1767
+ let ffi_str = err. to_string ( ) ;
1768
+ unsafe {
1769
+ cb (
1770
+ context,
1771
+ FFISlice :: empty ( ) ,
1772
+ Error :: DatabaseError ( ffi_str. as_str ( ) . into ( ) ) ,
1773
+ )
1774
+ } ;
1775
+ }
1776
+ }
1777
+ } ;
1778
+
1779
+ let f = |err : String | {
1780
+ unsafe {
1781
+ cb (
1782
+ context,
1783
+ FFISlice :: empty ( ) ,
1784
+ Error :: RuntimeError ( err. as_str ( ) . into ( ) ) ,
1785
+ )
1786
+ } ;
1787
+ } ;
1788
+ spawn_fut ! (
1789
+ fut,
1790
+ cb( context, FFISlice :: empty( ) , Error :: MissingRuntimeError ) ,
1791
+ f
1792
+ ) ;
1793
+ }
1794
+
1544
1795
/**
1545
1796
This function inserts a row into the database.
1546
1797
0 commit comments