sqlframe 2.4.0__py3-none-any.whl → 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sqlframe/__init__.py CHANGED
@@ -0,0 +1,83 @@
1
+ from __future__ import annotations
2
+
3
+ import importlib
4
+ import sys
5
+ import typing as t
6
+ from unittest.mock import MagicMock
7
+
8
+ if t.TYPE_CHECKING:
9
+ from sqlframe.base.session import CONN
10
+
11
+ ENGINE_TO_PREFIX = {
12
+ "bigquery": "BigQuery",
13
+ "duckdb": "DuckDB",
14
+ "postgres": "Postgres",
15
+ "redshift": "Redshift",
16
+ "snowflake": "Snowflake",
17
+ "spark": "Spark",
18
+ "standalone": "Standalone",
19
+ }
20
+
21
+ NAME_TO_FILE_OVERRIDE = {
22
+ "DataFrameNaFunctions": "dataframe",
23
+ "DataFrameStatFunctions": "dataframe",
24
+ "DataFrameReader": "readwriter",
25
+ "DataFrameWriter": "readwriter",
26
+ "GroupedData": "group",
27
+ "SparkSession": "session",
28
+ "WindowSpec": "window",
29
+ "UDFRegistration": "udf",
30
+ }
31
+
32
+ ACTIVATE_CONFIG = {}
33
+
34
+
35
+ def activate(
36
+ engine: t.Optional[str] = None,
37
+ conn: t.Optional[CONN] = None,
38
+ config: t.Optional[t.Dict[str, t.Any]] = None,
39
+ ) -> None:
40
+ import sqlframe
41
+ from sqlframe import testing
42
+
43
+ pyspark_mock = MagicMock()
44
+ pyspark_mock.__file__ = "pyspark"
45
+ sys.modules["pyspark"] = pyspark_mock
46
+ pyspark_mock.testing = testing
47
+ sys.modules["pyspark.testing"] = testing
48
+ if conn:
49
+ ACTIVATE_CONFIG["sqlframe.conn"] = conn
50
+ for key, value in (config or {}).items():
51
+ ACTIVATE_CONFIG[key] = value
52
+ if not engine:
53
+ return
54
+ engine = engine.lower()
55
+ if engine not in ENGINE_TO_PREFIX:
56
+ raise ValueError(
57
+ f"Unsupported engine {engine}. Supported engines are {', '.join(ENGINE_TO_PREFIX)}"
58
+ )
59
+ prefix = ENGINE_TO_PREFIX[engine]
60
+ engine_module = importlib.import_module(f"sqlframe.{engine}")
61
+
62
+ sys.modules["pyspark.sql"] = engine_module
63
+ pyspark_mock.sql = engine_module
64
+ types = engine_module.__dict__.copy()
65
+ resolved_files = set()
66
+ for name, obj in types.items():
67
+ if name.startswith(prefix) or name in [
68
+ "Column",
69
+ "Window",
70
+ "WindowSpec",
71
+ "functions",
72
+ "types",
73
+ ]:
74
+ name_without_prefix = name.replace(prefix, "")
75
+ if name_without_prefix == "Session":
76
+ name_without_prefix = "SparkSession"
77
+ setattr(engine_module, name_without_prefix, obj)
78
+ file = NAME_TO_FILE_OVERRIDE.get(name_without_prefix, name_without_prefix).lower()
79
+ engine_file = importlib.import_module(f"sqlframe.{engine}.{file}")
80
+ if engine_file not in resolved_files:
81
+ sys.modules[f"pyspark.sql.{file}"] = engine_file
82
+ resolved_files.add(engine_file)
83
+ setattr(engine_file, name_without_prefix, obj)
sqlframe/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '2.4.0'
16
- __version_tuple__ = version_tuple = (2, 4, 0)
15
+ __version__ = version = '3.0.0'
16
+ __version_tuple__ = version_tuple = (3, 0, 0)
@@ -42,6 +42,7 @@ else:
42
42
 
43
43
  if t.TYPE_CHECKING:
44
44
  import pandas as pd
45
+ from pyarrow import RecordBatchReader
45
46
  from pyarrow import Table as ArrowTable
46
47
  from sqlglot.dialects.dialect import DialectType
47
48
 
@@ -1815,5 +1816,14 @@ class _BaseDataFrame(t.Generic[SESSION, WRITER, NA, STAT, GROUP_DATA]):
1815
1816
 
1816
1817
  return self.select(covar_samp(col_func(col1), col_func(col2))).collect()[0][0]
1817
1818
 
1818
- def toArrow(self) -> ArrowTable:
1819
+ @t.overload
1820
+ def toArrow(self) -> ArrowTable: ...
1821
+
1822
+ @t.overload
1823
+ def toArrow(self, batch_size: int) -> RecordBatchReader: ...
1824
+
1825
+ def toArrow(self, batch_size: t.Optional[int] = None) -> t.Union[ArrowTable, RecordBatchReader]:
1826
+ """
1827
+ `batch_size` and `RecordBatchReader` are not part of the PySpark API
1828
+ """
1819
1829
  raise NotImplementedError("Arrow conversion is not supported by this engine")
sqlframe/base/session.py CHANGED
@@ -605,6 +605,10 @@ class _BaseSession(t.Generic[CATALOG, READER, WRITER, DF, CONN, UDF_REGISTRATION
605
605
  return _BaseSession(**self._session_kwargs)
606
606
 
607
607
  def getOrCreate(self) -> _BaseSession:
608
+ from sqlframe import ACTIVATE_CONFIG
609
+
610
+ for k, v in ACTIVATE_CONFIG.items():
611
+ self._set_config(k, v)
608
612
  self._set_session_properties()
609
613
  return self.session
610
614
 
@@ -1,23 +1,32 @@
1
1
  from sqlframe.bigquery.catalog import BigQueryCatalog
2
2
  from sqlframe.bigquery.column import Column
3
- from sqlframe.bigquery.dataframe import BigQueryDataFrame, BigQueryDataFrameNaFunctions
3
+ from sqlframe.bigquery.dataframe import (
4
+ BigQueryDataFrame,
5
+ BigQueryDataFrameNaFunctions,
6
+ BigQueryDataFrameStatFunctions,
7
+ )
4
8
  from sqlframe.bigquery.group import BigQueryGroupedData
5
9
  from sqlframe.bigquery.readwriter import (
6
10
  BigQueryDataFrameReader,
7
11
  BigQueryDataFrameWriter,
8
12
  )
9
13
  from sqlframe.bigquery.session import BigQuerySession
14
+ from sqlframe.bigquery.types import Row
15
+ from sqlframe.bigquery.udf import BigQueryUDFRegistration
10
16
  from sqlframe.bigquery.window import Window, WindowSpec
11
17
 
12
18
  __all__ = [
13
19
  "BigQueryCatalog",
14
- "Column",
15
20
  "BigQueryDataFrame",
16
21
  "BigQueryDataFrameNaFunctions",
17
22
  "BigQueryGroupedData",
18
23
  "BigQueryDataFrameReader",
19
24
  "BigQueryDataFrameWriter",
20
25
  "BigQuerySession",
26
+ "BigQueryDataFrameStatFunctions",
27
+ "BigQueryUDFRegistration",
28
+ "Column",
29
+ "Row",
21
30
  "Window",
22
31
  "WindowSpec",
23
32
  ]
@@ -84,7 +84,6 @@ class BigQuerySession(
84
84
  return BigQuerySession(**self._session_kwargs)
85
85
 
86
86
  def getOrCreate(self) -> BigQuerySession:
87
- self._set_session_properties()
88
- return self.session
87
+ return super().getOrCreate() # type: ignore
89
88
 
90
89
  builder = Builder()
@@ -1,20 +1,29 @@
1
1
  from sqlframe.duckdb.catalog import DuckDBCatalog
2
- from sqlframe.duckdb.column import DuckDBColumn
3
- from sqlframe.duckdb.dataframe import DuckDBDataFrame, DuckDBDataFrameNaFunctions
2
+ from sqlframe.duckdb.column import Column
3
+ from sqlframe.duckdb.dataframe import (
4
+ DuckDBDataFrame,
5
+ DuckDBDataFrameNaFunctions,
6
+ DuckDBDataFrameStatFunctions,
7
+ )
4
8
  from sqlframe.duckdb.group import DuckDBGroupedData
5
9
  from sqlframe.duckdb.readwriter import DuckDBDataFrameReader, DuckDBDataFrameWriter
6
10
  from sqlframe.duckdb.session import DuckDBSession
11
+ from sqlframe.duckdb.types import Row
12
+ from sqlframe.duckdb.udf import DuckDBUDFRegistration
7
13
  from sqlframe.duckdb.window import Window, WindowSpec
8
14
 
9
15
  __all__ = [
16
+ "Column",
10
17
  "DuckDBCatalog",
11
- "DuckDBColumn",
12
18
  "DuckDBDataFrame",
13
19
  "DuckDBDataFrameNaFunctions",
14
20
  "DuckDBGroupedData",
15
21
  "DuckDBDataFrameReader",
16
22
  "DuckDBDataFrameWriter",
17
23
  "DuckDBSession",
24
+ "DuckDBDataFrameStatFunctions",
25
+ "DuckDBUDFRegistration",
26
+ "Row",
18
27
  "Window",
19
28
  "WindowSpec",
20
29
  ]
sqlframe/duckdb/column.py CHANGED
@@ -1 +1 @@
1
- from sqlframe.base.column import Column as DuckDBColumn
1
+ from sqlframe.base.column import Column
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
- import sys
5
4
  import typing as t
6
5
 
7
6
  from sqlframe.base.dataframe import (
@@ -19,8 +18,7 @@ if t.TYPE_CHECKING:
19
18
  from sqlframe.duckdb.session import DuckDBSession # noqa
20
19
  from sqlframe.duckdb.readwriter import DuckDBDataFrameWriter # noqa
21
20
  from sqlframe.duckdb.group import DuckDBGroupedData # noqa
22
- from pyarrow import Table as ArrowTable
23
-
21
+ from pyarrow import Table as ArrowTable, RecordBatchReader
24
22
 
25
23
  logger = logging.getLogger(__name__)
26
24
 
@@ -48,6 +46,14 @@ class DuckDBDataFrame(
48
46
  _stat = DuckDBDataFrameStatFunctions
49
47
  _group_data = DuckDBGroupedData
50
48
 
51
- def toArrow(self) -> ArrowTable:
49
+ @t.overload
50
+ def toArrow(self) -> ArrowTable: ...
51
+
52
+ @t.overload
53
+ def toArrow(self, batch_size: int) -> RecordBatchReader: ...
54
+
55
+ def toArrow(self, batch_size: t.Optional[int] = None) -> t.Union[ArrowTable, RecordBatchReader]:
52
56
  self._collect(skip_rows=True)
53
- return self.session._last_result.arrow()
57
+ if not batch_size:
58
+ return self.session._last_result.arrow()
59
+ return self.session._last_result.fetch_record_batch(batch_size)
@@ -69,7 +69,6 @@ class DuckDBSession(
69
69
  return DuckDBSession(**self._session_kwargs)
70
70
 
71
71
  def getOrCreate(self) -> DuckDBSession:
72
- self._set_session_properties()
73
- return self.session
72
+ return super().getOrCreate() # type: ignore
74
73
 
75
74
  builder = Builder()
@@ -1,23 +1,32 @@
1
1
  from sqlframe.postgres.catalog import PostgresCatalog
2
2
  from sqlframe.postgres.column import Column
3
- from sqlframe.postgres.dataframe import PostgresDataFrame, PostgresDataFrameNaFunctions
3
+ from sqlframe.postgres.dataframe import (
4
+ PostgresDataFrame,
5
+ PostgresDataFrameNaFunctions,
6
+ PostgresDataFrameStatFunctions,
7
+ )
4
8
  from sqlframe.postgres.group import PostgresGroupedData
5
9
  from sqlframe.postgres.readwriter import (
6
10
  PostgresDataFrameReader,
7
11
  PostgresDataFrameWriter,
8
12
  )
9
13
  from sqlframe.postgres.session import PostgresSession
14
+ from sqlframe.postgres.types import Row
15
+ from sqlframe.postgres.udf import PostgresUDFRegistration
10
16
  from sqlframe.postgres.window import Window, WindowSpec
11
17
 
12
18
  __all__ = [
13
- "PostgresCatalog",
14
19
  "Column",
20
+ "PostgresCatalog",
15
21
  "PostgresDataFrame",
16
22
  "PostgresDataFrameNaFunctions",
17
23
  "PostgresGroupedData",
18
24
  "PostgresDataFrameReader",
19
25
  "PostgresDataFrameWriter",
20
26
  "PostgresSession",
27
+ "PostgresDataFrameStatFunctions",
28
+ "PostgresUDFRegistration",
29
+ "Row",
21
30
  "Window",
22
31
  "WindowSpec",
23
32
  ]
@@ -79,7 +79,6 @@ $$ LANGUAGE plpgsql;""")
79
79
  return PostgresSession(**self._session_kwargs)
80
80
 
81
81
  def getOrCreate(self) -> PostgresSession:
82
- self._set_session_properties()
83
- return self.session
82
+ return super().getOrCreate() # type: ignore
84
83
 
85
84
  builder = Builder()
@@ -1,23 +1,32 @@
1
1
  from sqlframe.redshift.catalog import RedshiftCatalog
2
2
  from sqlframe.redshift.column import Column
3
- from sqlframe.redshift.dataframe import RedshiftDataFrame, RedshiftDataFrameNaFunctions
3
+ from sqlframe.redshift.dataframe import (
4
+ RedshiftDataFrame,
5
+ RedshiftDataFrameNaFunctions,
6
+ RedshiftDataFrameStatFunctions,
7
+ )
4
8
  from sqlframe.redshift.group import RedshiftGroupedData
5
9
  from sqlframe.redshift.readwriter import (
6
10
  RedshiftDataFrameReader,
7
11
  RedshiftDataFrameWriter,
8
12
  )
9
13
  from sqlframe.redshift.session import RedshiftSession
14
+ from sqlframe.redshift.types import Row
15
+ from sqlframe.redshift.udf import RedshiftUDFRegistration
10
16
  from sqlframe.redshift.window import Window, WindowSpec
11
17
 
12
18
  __all__ = [
13
- "RedshiftCatalog",
14
19
  "Column",
20
+ "RedshiftCatalog",
15
21
  "RedshiftDataFrame",
16
22
  "RedshiftDataFrameNaFunctions",
17
23
  "RedshiftGroupedData",
18
24
  "RedshiftDataFrameReader",
19
25
  "RedshiftDataFrameWriter",
20
26
  "RedshiftSession",
27
+ "RedshiftDataFrameStatFunctions",
28
+ "RedshiftUDFRegistration",
29
+ "Row",
21
30
  "Window",
22
31
  "WindowSpec",
23
32
  ]
@@ -49,7 +49,6 @@ class RedshiftSession(
49
49
  return RedshiftSession(**self._session_kwargs)
50
50
 
51
51
  def getOrCreate(self) -> RedshiftSession:
52
- self._set_session_properties()
53
- return self.session
52
+ return super().getOrCreate() # type: ignore
54
53
 
55
54
  builder = Builder()
@@ -3,6 +3,7 @@ from sqlframe.snowflake.column import Column
3
3
  from sqlframe.snowflake.dataframe import (
4
4
  SnowflakeDataFrame,
5
5
  SnowflakeDataFrameNaFunctions,
6
+ SnowflakeDataFrameStatFunctions,
6
7
  )
7
8
  from sqlframe.snowflake.group import SnowflakeGroupedData
8
9
  from sqlframe.snowflake.readwriter import (
@@ -10,17 +11,22 @@ from sqlframe.snowflake.readwriter import (
10
11
  SnowflakeDataFrameWriter,
11
12
  )
12
13
  from sqlframe.snowflake.session import SnowflakeSession
14
+ from sqlframe.snowflake.types import Row
15
+ from sqlframe.snowflake.udf import SnowflakeUDFRegistration
13
16
  from sqlframe.snowflake.window import Window, WindowSpec
14
17
 
15
18
  __all__ = [
16
- "SnowflakeCatalog",
17
19
  "Column",
20
+ "Row",
21
+ "SnowflakeCatalog",
18
22
  "SnowflakeDataFrame",
19
23
  "SnowflakeDataFrameNaFunctions",
20
24
  "SnowflakeGroupedData",
21
25
  "SnowflakeDataFrameReader",
22
26
  "SnowflakeDataFrameWriter",
23
27
  "SnowflakeSession",
28
+ "SnowflakeDataFrameStatFunctions",
29
+ "SnowflakeUDFRegistration",
24
30
  "Window",
25
31
  "WindowSpec",
26
32
  ]
@@ -86,7 +86,6 @@ class SnowflakeSession(
86
86
  return SnowflakeSession(**self._session_kwargs)
87
87
 
88
88
  def getOrCreate(self) -> SnowflakeSession:
89
- self._set_session_properties()
90
- return self.session
89
+ return super().getOrCreate() # type: ignore
91
90
 
92
91
  builder = Builder()
@@ -1,23 +1,32 @@
1
1
  from sqlframe.spark.catalog import SparkCatalog
2
2
  from sqlframe.spark.column import Column
3
- from sqlframe.spark.dataframe import SparkDataFrame, SparkDataFrameNaFunctions
3
+ from sqlframe.spark.dataframe import (
4
+ SparkDataFrame,
5
+ SparkDataFrameNaFunctions,
6
+ SparkDataFrameStatFunctions,
7
+ )
4
8
  from sqlframe.spark.group import SparkGroupedData
5
9
  from sqlframe.spark.readwriter import (
6
10
  SparkDataFrameReader,
7
11
  SparkDataFrameWriter,
8
12
  )
9
13
  from sqlframe.spark.session import SparkSession
14
+ from sqlframe.spark.types import Row
15
+ from sqlframe.spark.udf import SparkUDFRegistration
10
16
  from sqlframe.spark.window import Window, WindowSpec
11
17
 
12
18
  __all__ = [
13
- "SparkCatalog",
14
19
  "Column",
20
+ "Row",
21
+ "SparkCatalog",
15
22
  "SparkDataFrame",
16
23
  "SparkDataFrameNaFunctions",
17
24
  "SparkGroupedData",
18
25
  "SparkDataFrameReader",
19
26
  "SparkDataFrameWriter",
20
27
  "SparkSession",
28
+ "SparkDataFrameStatFunctions",
29
+ "SparkUDFRegistration",
21
30
  "Window",
22
31
  "WindowSpec",
23
32
  ]
sqlframe/spark/session.py CHANGED
@@ -162,5 +162,4 @@ class SparkSession(
162
162
  return SparkSession(**self._session_kwargs)
163
163
 
164
164
  def getOrCreate(self) -> SparkSession:
165
- self._set_session_properties()
166
- return self.session
165
+ return super().getOrCreate() # type: ignore
@@ -3,6 +3,7 @@ from sqlframe.standalone.column import Column
3
3
  from sqlframe.standalone.dataframe import (
4
4
  StandaloneDataFrame,
5
5
  StandaloneDataFrameNaFunctions,
6
+ StandaloneDataFrameStatFunctions,
6
7
  )
7
8
  from sqlframe.standalone.group import StandaloneGroupedData
8
9
  from sqlframe.standalone.readwriter import (
@@ -10,17 +11,22 @@ from sqlframe.standalone.readwriter import (
10
11
  StandaloneDataFrameWriter,
11
12
  )
12
13
  from sqlframe.standalone.session import StandaloneSession
14
+ from sqlframe.standalone.types import Row
15
+ from sqlframe.standalone.udf import StandaloneUDFRegistration
13
16
  from sqlframe.standalone.window import Window, WindowSpec
14
17
 
15
18
  __all__ = [
16
- "StandaloneCatalog",
17
19
  "Column",
20
+ "Row",
21
+ "StandaloneCatalog",
18
22
  "StandaloneDataFrame",
19
23
  "StandaloneDataFrameNaFunctions",
20
24
  "StandaloneGroupedData",
21
25
  "StandaloneDataFrameReader",
22
26
  "StandaloneDataFrameWriter",
23
27
  "StandaloneSession",
28
+ "StandaloneDataFrameStatFunctions",
29
+ "StandaloneUDFRegistration",
24
30
  "Window",
25
31
  "WindowSpec",
26
32
  ]
@@ -37,7 +37,6 @@ class StandaloneSession(
37
37
  return StandaloneSession()
38
38
 
39
39
  def getOrCreate(self) -> StandaloneSession:
40
- self._set_session_properties()
41
- return self.session
40
+ return super().getOrCreate() # type: ignore
42
41
 
43
42
  builder = Builder()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sqlframe
3
- Version: 2.4.0
3
+ Version: 3.0.0
4
4
  Summary: Turning PySpark Into a Universal DataFrame API
5
5
  Home-page: https://github.com/eakmanrq/sqlframe
6
6
  Author: Ryan Eakman
@@ -25,6 +25,7 @@ Requires-Dist: google-cloud-bigquery-storage (<3,>=2) ; extra == 'bigquery'
25
25
  Requires-Dist: google-cloud-bigquery[pandas] (<4,>=3) ; extra == 'bigquery'
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: duckdb (<1.1,>=0.9) ; extra == 'dev'
28
+ Requires-Dist: findspark (<3,>=2) ; extra == 'dev'
28
29
  Requires-Dist: mypy (<1.12,>=1.10.0) ; extra == 'dev'
29
30
  Requires-Dist: openai (<1.43,>=1.30) ; extra == 'dev'
30
31
  Requires-Dist: pandas-stubs (<3,>=2) ; extra == 'dev'
@@ -81,10 +82,10 @@ SQLFrame also has a "Standalone" session that be used to generate SQL without an
81
82
 
82
83
  SQLFrame is great for:
83
84
 
84
- * Users who want to run PySpark DataFrame code without having to use a Spark cluster
85
+ * Users who want a DataFrame API that leverages the full power of their engine to do the processing
86
+ * Users who want to run PySpark code quickly locally without the overhead of starting a Spark session
85
87
  * Users who want a SQL representation of their DataFrame code for debugging or sharing with others
86
- * See [Spark Engine](https://sqlframe.readthedocs.io/en/stable/spark/) for more details
87
- * Users who want a DataFrame API that leverages the full power of their engine to do the processing
88
+ * Users who want to run PySpark DataFrame code without the complexity of using Spark for processing
88
89
 
89
90
  ## Installation
90
91
 
@@ -108,44 +109,72 @@ See specific engine documentation for additional setup instructions.
108
109
  ## Configuration
109
110
 
110
111
  SQLFrame generates consistently accurate yet complex SQL for engine execution.
111
- However, when using df.sql(), it produces more human-readable SQL.
112
+ However, when using df.sql(optimize=True), it produces more human-readable SQL.
112
113
  For details on how to configure this output and leverage OpenAI to enhance the SQL, see [Generated SQL Configuration](https://sqlframe.readthedocs.io/en/stable/configuration/#generated-sql).
113
114
 
114
115
  SQLFrame by default uses the Spark dialect for input and output.
115
116
  This can be changed to make SQLFrame feel more like a native DataFrame API for the engine you are using.
116
117
  See [Input and Output Dialect Configuration](https://sqlframe.readthedocs.io/en/stable/configuration/#input-and-output-dialect).
117
118
 
119
+ ## Activating SQLFrame
120
+
121
+ SQLFrame can either replace pyspark imports or be used alongside them.
122
+ To replace pyspark imports, use the [activate function](https://sqlframe.readthedocs.io/en/stable/configuration/#activating-sqlframe) to set the engine to use.
123
+
124
+ ```python
125
+ from sqlframe import activate
126
+
127
+ # Activate SQLFrame to run directly on DuckDB
128
+ activate(engine="duckdb")
129
+
130
+ from pyspark.sql import SparkSession
131
+ session = SparkSession.builder.getOrCreate()
132
+ ```
133
+
134
+ SQLFrame can also be directly imported which both maintains pyspark imports but also allows for a more engine-native DataFrame API:
135
+
136
+ ```python
137
+ from sqlframe.duckdb import DuckDBSession
138
+
139
+ session = DuckDBSession.builder.getOrCreate()
140
+ ```
141
+
118
142
  ## Example Usage
119
143
 
120
144
  ```python
121
- from sqlframe.bigquery import BigQuerySession
122
- from sqlframe.bigquery import functions as F
123
- from sqlframe.bigquery import Window
145
+ from sqlframe import activate
146
+
147
+ # Activate SQLFrame to run directly on BigQuery
148
+ activate(engine="bigquery")
149
+
150
+ from pyspark.sql import SparkSession
151
+ from pyspark.sql import functions as F
152
+ from pyspark.sql import Window
124
153
 
125
- session = BigQuerySession()
154
+ session = SparkSession.builder.getOrCreate()
126
155
  table_path = '"bigquery-public-data".samples.natality'
127
156
  # Top 5 years with the greatest year-over-year % change in new families with single child
128
157
  df = (
129
- session.table(table_path)
130
- .where(F.col("ever_born") == 1)
131
- .groupBy("year")
132
- .agg(F.count("*").alias("num_single_child_families"))
133
- .withColumn(
134
- "last_year_num_single_child_families",
135
- F.lag(F.col("num_single_child_families"), 1).over(Window.orderBy("year"))
136
- )
137
- .withColumn(
138
- "percent_change",
139
- (F.col("num_single_child_families") - F.col("last_year_num_single_child_families"))
140
- / F.col("last_year_num_single_child_families")
141
- )
142
- .orderBy(F.abs(F.col("percent_change")).desc())
143
- .select(
144
- F.col("year").alias("year"),
145
- F.format_number("num_single_child_families", 0).alias("new families single child"),
146
- F.format_number(F.col("percent_change") * 100, 2).alias("percent change"),
147
- )
148
- .limit(5)
158
+ session.table(table_path)
159
+ .where(F.col("ever_born") == 1)
160
+ .groupBy("year")
161
+ .agg(F.count("*").alias("num_single_child_families"))
162
+ .withColumn(
163
+ "last_year_num_single_child_families",
164
+ F.lag(F.col("num_single_child_families"), 1).over(Window.orderBy("year"))
165
+ )
166
+ .withColumn(
167
+ "percent_change",
168
+ (F.col("num_single_child_families") - F.col("last_year_num_single_child_families"))
169
+ / F.col("last_year_num_single_child_families")
170
+ )
171
+ .orderBy(F.abs(F.col("percent_change")).desc())
172
+ .select(
173
+ F.col("year").alias("year"),
174
+ F.format_number("num_single_child_families", 0).alias("new families single child"),
175
+ F.format_number(F.col("percent_change") * 100, 2).alias("percent change"),
176
+ )
177
+ .limit(5)
149
178
  )
150
179
  ```
151
180
  ```python
@@ -1,10 +1,10 @@
1
- sqlframe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- sqlframe/_version.py,sha256=NXpAHvzuYHxlLDJV0489874frLu4dA2joFw1iHLLrOg,411
1
+ sqlframe/__init__.py,sha256=vpa_uyTR93861-mffYN9cJbjAXhQIr6pmfDPlaZKF6M,2583
2
+ sqlframe/_version.py,sha256=E9sjrmgE4U1biRnH7SOU6xOu4ABa14HHotRIgXR086E,411
3
3
  sqlframe/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  sqlframe/base/_typing.py,sha256=b2clI5HI1zEZKB_3Msx3FeAJQyft44ubUifJwQRVXyQ,1298
5
5
  sqlframe/base/catalog.py,sha256=SzFQalTWdhWzxUY-4ut1f9TfOECp_JmJEgNPfrRKCe0,38457
6
6
  sqlframe/base/column.py,sha256=C2xj6OHMsJbEgjbI-m5HuIvqHYt2DbbUtCjssKpplNk,17748
7
- sqlframe/base/dataframe.py,sha256=CHoSK7g9ceuX_4c8yL3nbq1nb15dGt2g_W0UBlBA-Nc,71132
7
+ sqlframe/base/dataframe.py,sha256=wIYKaV9xzILPVmAcujvRmbH-6dbKPx6hVNHNWCEuayM,71479
8
8
  sqlframe/base/decorators.py,sha256=Jy4bf8MhZ-AJ6CWTj59bBJRqamtLbPC0USUMFrY6g0w,449
9
9
  sqlframe/base/exceptions.py,sha256=9Uwvqn2eAkDpqm4BrRgbL61qM-GMCbJEMAW8otxO46s,370
10
10
  sqlframe/base/function_alternatives.py,sha256=IxNBqplehkAEkpzA625Dif-9Xyi4Hrho81A9U262rV0,50714
@@ -13,7 +13,7 @@ sqlframe/base/group.py,sha256=TES9CleVmH3x-0X-tqmuUKfCKSWjH5vg1aU3R6dDmFc,4059
13
13
  sqlframe/base/normalize.py,sha256=nXAJ5CwxVf4DV0GsH-q1w0p8gmjSMlv96k_ez1eVul8,3880
14
14
  sqlframe/base/operations.py,sha256=-AhNuEzcV7ZExoP1oY3blaKip-joQyJeQVvfBTs_2g4,3456
15
15
  sqlframe/base/readerwriter.py,sha256=FkImnUR_qNASmXktk0JDsFeOzfh799hd09vI2uznNH8,25350
16
- sqlframe/base/session.py,sha256=YGlrc5nB2TOtrAzzgHynrkdRyl39DqczurnxyoqcfTg,25024
16
+ sqlframe/base/session.py,sha256=DgkzSKFc3LdzXiqB9ofsh47Ygivq2-Or6J2XbDLzxVs,25162
17
17
  sqlframe/base/transforms.py,sha256=y0j3SGDz3XCmNGrvassk1S-owllUWfkHyMgZlY6SFO4,467
18
18
  sqlframe/base/types.py,sha256=iBNk9bpFtb2NBIogYS8i7OlQZMRvpR6XxqzBebsjQDU,12280
19
19
  sqlframe/base/udf.py,sha256=O6hMhBUy9NVv-mhJRtfFhXTIa_-Z8Y_FkmmuOHu0l90,1117
@@ -23,7 +23,7 @@ sqlframe/base/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
23
23
  sqlframe/base/mixins/catalog_mixins.py,sha256=9tn0mK8oPoqIIjNItystD5tdBMdK9YpkxTG7G9KQl8k,18619
24
24
  sqlframe/base/mixins/dataframe_mixins.py,sha256=3MMQu2hdHG_qtDQ6jDHo0Iy5KtLj4lHePfovCVxTqbo,1411
25
25
  sqlframe/base/mixins/readwriter_mixins.py,sha256=QnxGVL8ftZfYlBNG0Bl24N_bnA2YioSxUsTSgKIbuvQ,4723
26
- sqlframe/bigquery/__init__.py,sha256=i2NsMbiXOj2xphCtPuNk6cVw4iYeq5_B1I9dVI9aGAk,712
26
+ sqlframe/bigquery/__init__.py,sha256=kbaomhYAANPdxeDQhajv8IHfMg_ENKivtYK-rPwaV08,939
27
27
  sqlframe/bigquery/catalog.py,sha256=8d36IzT5GPWd1FdxJ9vEljOdbIDepHnFOBjwP0bX6FE,11625
28
28
  sqlframe/bigquery/column.py,sha256=E1tUa62Y5HajkhgFuebU9zohrGyieudcHzTT8gfalio,40
29
29
  sqlframe/bigquery/dataframe.py,sha256=Y2uy4FEYw0KxIHgnaA9uMwdIzxJzTlD_NSzIe7P7kxA,2405
@@ -31,23 +31,23 @@ sqlframe/bigquery/functions.py,sha256=CxXiBzSLRf9h-9lAM8xSz1CFcVk2tVXU1eFPJ4d_L0
31
31
  sqlframe/bigquery/functions.pyi,sha256=BCYqHpZzv4KWVtTuiC9wCSzXdxeHsz9gwkEvKzwHnoY,13583
32
32
  sqlframe/bigquery/group.py,sha256=UVBNBRTo8OqS-_cS5YwvTeJYgYxeG-d6R3kfyHmlFqw,391
33
33
  sqlframe/bigquery/readwriter.py,sha256=WAD3ZMwkkjOpvPPoZXfaLLNM6tRTeUvdEj-hQZAzXeo,870
34
- sqlframe/bigquery/session.py,sha256=-ySvZGbV-EeUJ6Z1SEFT8Es_80Lu3Db0WF333ktxoIQ,2762
34
+ sqlframe/bigquery/session.py,sha256=uSiEWWiDEryq3gIJJUmsu1DIalRGomNiymVulxt439c,2744
35
35
  sqlframe/bigquery/types.py,sha256=KwNyuXIo-2xVVd4bZED3YrQOobKCtemlxGrJL7DrTC8,34
36
36
  sqlframe/bigquery/udf.py,sha256=ZZ1-P1zWZhQqmhBqwAxfNeKl31nDkkZgkuz7Dn28P_0,264
37
37
  sqlframe/bigquery/window.py,sha256=6GKPzuxeSapJakBaKBeT9VpED1ACdjggDv9JRILDyV0,35
38
- sqlframe/duckdb/__init__.py,sha256=t85TA3ufZtL1weQNFmEs8itCSwbJFtw03-p0GT4XGf8,669
38
+ sqlframe/duckdb/__init__.py,sha256=KAw_uZEhFMwi3D9Wj6AgHAKqLNk-EAx2uDIYu56oL44,872
39
39
  sqlframe/duckdb/catalog.py,sha256=YYYVmetLUaJOdObKw4AJ7L0P-msshkta4xHlcZQ9zEA,4795
40
- sqlframe/duckdb/column.py,sha256=wkEPcp3xVsH5nC3kpacXqNkRv9htPtBgt-0uFRxIRNs,56
41
- sqlframe/duckdb/dataframe.py,sha256=QYFFj6a2uYpJUGB-s0MEX2z7HgjfPbL6ZKI4BFjVI6o,1394
40
+ sqlframe/duckdb/column.py,sha256=E1tUa62Y5HajkhgFuebU9zohrGyieudcHzTT8gfalio,40
41
+ sqlframe/duckdb/dataframe.py,sha256=HZg_uMAz4RsubZJT4-MslUQS_0-InF0_P5Yq5HyJ3wE,1708
42
42
  sqlframe/duckdb/functions.py,sha256=Ee8o6YFtRdEiq0jNLXxgu5lcbc7Tsg0-lK6oRyxdcjo,1920
43
43
  sqlframe/duckdb/functions.pyi,sha256=Qn6j4zwwuBsh6q9341dR3Z5kpeRsgvM4u6Bb6FekKrI,5827
44
44
  sqlframe/duckdb/group.py,sha256=IkhbW42Ng1U5YT3FkIdiB4zBqRkW4QyTb-1detY1e_4,383
45
45
  sqlframe/duckdb/readwriter.py,sha256=0qZcARQoWYlx9P2m0uS2vuMj_tG_ka4NhHzg7qdaR3I,4597
46
- sqlframe/duckdb/session.py,sha256=dj8kOTklBHKTyFGc3UwbgFlloPnfIDUf1Sh4uaO1hSg,2340
46
+ sqlframe/duckdb/session.py,sha256=Pho9H74_0xNQPP_oBdFa4aflBAsrxvpXPMQGSKyq1-4,2322
47
47
  sqlframe/duckdb/types.py,sha256=KwNyuXIo-2xVVd4bZED3YrQOobKCtemlxGrJL7DrTC8,34
48
48
  sqlframe/duckdb/udf.py,sha256=Du9LnOtT1lJvB90D4HSR2tB7MXy179jZngDR-EjVjQk,656
49
49
  sqlframe/duckdb/window.py,sha256=6GKPzuxeSapJakBaKBeT9VpED1ACdjggDv9JRILDyV0,35
50
- sqlframe/postgres/__init__.py,sha256=Sz_MtgV_oh_QhfZTC7iKM07ICUmNcJEDV0kEkSW9ZKU,712
50
+ sqlframe/postgres/__init__.py,sha256=NN9WI0-GehvpPdJmTB2VSDVpA5PAtxa3ZkF4BRcTEy4,939
51
51
  sqlframe/postgres/catalog.py,sha256=9XVXXDW04mY_KmeB52NsCny8n0evqdDCBxhGH1Xce6s,8956
52
52
  sqlframe/postgres/column.py,sha256=E1tUa62Y5HajkhgFuebU9zohrGyieudcHzTT8gfalio,40
53
53
  sqlframe/postgres/dataframe.py,sha256=f-w6UHxZtmeZ5oMbaqJaZ8FrYeOhzyveNlZOK57ke0k,1289
@@ -55,22 +55,22 @@ sqlframe/postgres/functions.py,sha256=iujyPmI6frOCD7pymgBby89DezPHm8dmt75sebhzRa
55
55
  sqlframe/postgres/functions.pyi,sha256=9s7W5QPZXPKqxY6XpkxLCHmC5sp1PkJg1LywgpWTz-k,5550
56
56
  sqlframe/postgres/group.py,sha256=KUXeSFKWTSH9yCRJAhW85OvjZaG6Zr4In9LR_ie3yGU,391
57
57
  sqlframe/postgres/readwriter.py,sha256=L1e3yKXzFVNR_W5s1DHaWol7G8x7l4jcZ5sLGualyMk,870
58
- sqlframe/postgres/session.py,sha256=LkM35-ADkIh2OSNT6HRVfJ8jLOoFlrdgkSSVhFGMYRc,2495
58
+ sqlframe/postgres/session.py,sha256=v030gVL6DEZb1utcqexupCC-8ouEumeLhvqRyvQfRew,2477
59
59
  sqlframe/postgres/types.py,sha256=KwNyuXIo-2xVVd4bZED3YrQOobKCtemlxGrJL7DrTC8,34
60
60
  sqlframe/postgres/udf.py,sha256=TylVxrmPzycAqnpTiueGvvetiMCfCX31QatgQMIgpME,264
61
61
  sqlframe/postgres/window.py,sha256=6GKPzuxeSapJakBaKBeT9VpED1ACdjggDv9JRILDyV0,35
62
- sqlframe/redshift/__init__.py,sha256=jamKYQtQaKjjXnQ01QGPHvatbrZSw9sWno_VOUGSz6I,712
62
+ sqlframe/redshift/__init__.py,sha256=F43uqhCJYQk5wK8Ydvmn5KGrvt__IYaDVS0DJ_-izhc,939
63
63
  sqlframe/redshift/catalog.py,sha256=x-sfVwoOS_0MeLICCqu7YUiFRgBam7vV1sHfaAKZGjE,5410
64
64
  sqlframe/redshift/column.py,sha256=E1tUa62Y5HajkhgFuebU9zohrGyieudcHzTT8gfalio,40
65
65
  sqlframe/redshift/dataframe.py,sha256=aTC0DOPDFwWH1_b9T0Pif80cYSGudIp0D-cmkR7Ci_M,1104
66
66
  sqlframe/redshift/functions.py,sha256=DR5kodYAcKatUqopwrEQtxryI4ZSqaH47_y3WLht4Wg,455
67
67
  sqlframe/redshift/group.py,sha256=5MGZYJfHpzoRSQ0N_pn4KUk4Mk2gocQwU3K1-jAbvGg,391
68
68
  sqlframe/redshift/readwriter.py,sha256=g3FYKSsJKqcSnElprzzz29ZctoXq9tRB0Mj9Bm1HycI,870
69
- sqlframe/redshift/session.py,sha256=nqqFxplCcIa_mN59xq3yHclMQ_dKchwuodx31xog55o,1593
69
+ sqlframe/redshift/session.py,sha256=FKzypkZjuwU4A2DMe9vJTVJYdXGyl63jV72bToz6c4o,1575
70
70
  sqlframe/redshift/types.py,sha256=KwNyuXIo-2xVVd4bZED3YrQOobKCtemlxGrJL7DrTC8,34
71
71
  sqlframe/redshift/udf.py,sha256=xOi7vtO56MyYprC3ys3FCSVJ5EVjEq2l_KqEVgKJrkw,264
72
72
  sqlframe/redshift/window.py,sha256=6GKPzuxeSapJakBaKBeT9VpED1ACdjggDv9JRILDyV0,35
73
- sqlframe/snowflake/__init__.py,sha256=nuQ3cuHjDpW4ELZfbd2qOYmtXmcYl7MtsrdOrRdozo0,746
73
+ sqlframe/snowflake/__init__.py,sha256=msYAxOnPyjuBSTbpb5s9P5o0pr2N82UUGPxUtv0TNNw,966
74
74
  sqlframe/snowflake/catalog.py,sha256=Tp_B9oMTInnqLTiZNsT0UNc-a-aKXu3zFThlCwLeKCA,6507
75
75
  sqlframe/snowflake/column.py,sha256=E1tUa62Y5HajkhgFuebU9zohrGyieudcHzTT8gfalio,40
76
76
  sqlframe/snowflake/dataframe.py,sha256=ANDZ5Dpxz-WTlTtmKNcv-nJlzTeTsAOK0X0gR2euPqQ,2144
@@ -78,11 +78,11 @@ sqlframe/snowflake/functions.py,sha256=iX67xU8Czy5k3HiNjNbN-x-via6yqGNaMPw1maV9H
78
78
  sqlframe/snowflake/functions.pyi,sha256=wqUPXuZxjRY0rPY2BRAb7XXkWYP1DyuDzvlriRySdSw,6185
79
79
  sqlframe/snowflake/group.py,sha256=pPP1l2RRo_LgkXrji8a87n2PKo-63ZRPT-WUtvVcBME,395
80
80
  sqlframe/snowflake/readwriter.py,sha256=yhRc2HcMq6PwV3ghZWC-q-qaE7LE4aEjZEXCip4OOlQ,884
81
- sqlframe/snowflake/session.py,sha256=pCTb39olI5fzj7mrnuWupJs5EenDVDSH9goxueTXwiU,3338
81
+ sqlframe/snowflake/session.py,sha256=fnFYrJ9JxoOf4ZKTrQcSKjwr6wNp6A85cMqKczOi3vA,3320
82
82
  sqlframe/snowflake/types.py,sha256=KwNyuXIo-2xVVd4bZED3YrQOobKCtemlxGrJL7DrTC8,34
83
83
  sqlframe/snowflake/udf.py,sha256=yzMmky-n5BXFbdldgfzLP8hCrVm0DgruSUCUUy1_3sk,268
84
84
  sqlframe/snowflake/window.py,sha256=6GKPzuxeSapJakBaKBeT9VpED1ACdjggDv9JRILDyV0,35
85
- sqlframe/spark/__init__.py,sha256=WhYQAZMJN1EMNAVGUH7BEinxNdYtXOrrr-6HUniJOyI,649
85
+ sqlframe/spark/__init__.py,sha256=QV0eNmY5fL4ulLvAJVVVx2OYFfQXN2KYV3R5cij7HTg,858
86
86
  sqlframe/spark/catalog.py,sha256=3T4aivgQmAhPTmlVk53jk3VvFBJlp1pKvWKNmTHz1W8,39741
87
87
  sqlframe/spark/column.py,sha256=E1tUa62Y5HajkhgFuebU9zohrGyieudcHzTT8gfalio,40
88
88
  sqlframe/spark/dataframe.py,sha256=_TD-h7oz0-i80r90v17UoLDoIzcGNchU2SL13ujOOic,1779
@@ -90,25 +90,25 @@ sqlframe/spark/functions.py,sha256=AQfqfvaojJzCuo9DyDklz0JYZPhn_3dzWvztsklBO0o,5
90
90
  sqlframe/spark/functions.pyi,sha256=bjz6s8E6OB0c4KfTTsls7rhb_R9mIYvkaeaXefMziqM,11617
91
91
  sqlframe/spark/group.py,sha256=MrvV_v-YkBc6T1zz882WrEqtWjlooWIyHBCmTQg3fCA,379
92
92
  sqlframe/spark/readwriter.py,sha256=w68EImTcGJv64X7pc1tk5tDjDxb1nAnn-MiIaaN9Dc8,812
93
- sqlframe/spark/session.py,sha256=eYwEANEMkP6djzUlm-p1WPkB6QZ4cdW_P4sx1K1wOwQ,5283
93
+ sqlframe/spark/session.py,sha256=cjsRQZz1kW67aajvXQyAJkv9Uh-zmmk3C3O9QSBbEQQ,5265
94
94
  sqlframe/spark/types.py,sha256=KwNyuXIo-2xVVd4bZED3YrQOobKCtemlxGrJL7DrTC8,34
95
95
  sqlframe/spark/udf.py,sha256=owB8NDaGVkUQ0WGm7SZt2t9zfvLFCfi0W48QiPfgjck,1153
96
96
  sqlframe/spark/window.py,sha256=6GKPzuxeSapJakBaKBeT9VpED1ACdjggDv9JRILDyV0,35
97
- sqlframe/standalone/__init__.py,sha256=yu4A97HwhyDwllDEzG7io4ScyWipWSAH2tqUKS545OA,767
97
+ sqlframe/standalone/__init__.py,sha256=u-BbP0mkWWRgMz46pylFlnD3EsEBvjtMnQ6kVCAejww,993
98
98
  sqlframe/standalone/catalog.py,sha256=oJAPxrXtra_YP_JBZCJY2qsr0TRhWG7FFSq0RHDszcU,389
99
99
  sqlframe/standalone/column.py,sha256=E1tUa62Y5HajkhgFuebU9zohrGyieudcHzTT8gfalio,40
100
100
  sqlframe/standalone/dataframe.py,sha256=o6weWJvDX1w351p_14PQ52qopbPozVG9OFmhaqVvivU,967
101
101
  sqlframe/standalone/functions.py,sha256=NW-k7NP_Y9DzQq6fjX5-CL8oOUGAiaMo4SBuDd8-JUA,38
102
102
  sqlframe/standalone/group.py,sha256=oGEbAQMSm6AlkwnBxNI8r9enZWRwsRxc8zpzoz3rArk,399
103
103
  sqlframe/standalone/readwriter.py,sha256=EZNyDJ4ID6sGNog3uP4-e9RvchX4biJJDNtc5hkKkrY,633
104
- sqlframe/standalone/session.py,sha256=h8EpjZOt4GiDBkqEC5dFdkv5PtCDF9TkD9spqp4olSE,1338
104
+ sqlframe/standalone/session.py,sha256=ELrDkb2wW5FhpeKJEFCQvVREmPs7ulSfMj0ipRxPUCk,1320
105
105
  sqlframe/standalone/types.py,sha256=KwNyuXIo-2xVVd4bZED3YrQOobKCtemlxGrJL7DrTC8,34
106
106
  sqlframe/standalone/udf.py,sha256=azmgtUjHNIPs0WMVNId05SHwiYn41MKVBhKXsQJ5dmY,272
107
107
  sqlframe/standalone/window.py,sha256=6GKPzuxeSapJakBaKBeT9VpED1ACdjggDv9JRILDyV0,35
108
108
  sqlframe/testing/__init__.py,sha256=VVCosQhitU74A3NnE52O4mNtGZONapuEXcc20QmSlnQ,132
109
109
  sqlframe/testing/utils.py,sha256=9DDYVuocO7tygee3RaajuJNZ24sJwf_LY556kKg7kTw,13011
110
- sqlframe-2.4.0.dist-info/LICENSE,sha256=VZu79YgW780qxaFJMr0t5ZgbOYEh04xWoxaWOaqIGWk,1068
111
- sqlframe-2.4.0.dist-info/METADATA,sha256=dfjbBh14A6aUdyiaO4H-rqMVNyChQ7TgncCAwPjjcrQ,7812
112
- sqlframe-2.4.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
113
- sqlframe-2.4.0.dist-info/top_level.txt,sha256=T0_RpoygaZSF6heeWwIDQgaP0varUdSK1pzjeJZRjM8,9
114
- sqlframe-2.4.0.dist-info/RECORD,,
110
+ sqlframe-3.0.0.dist-info/LICENSE,sha256=VZu79YgW780qxaFJMr0t5ZgbOYEh04xWoxaWOaqIGWk,1068
111
+ sqlframe-3.0.0.dist-info/METADATA,sha256=HOOsdc0G7ea0HCIO_sY-gtr4RlXULTGFAAzxaGVMzEc,8639
112
+ sqlframe-3.0.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
113
+ sqlframe-3.0.0.dist-info/top_level.txt,sha256=T0_RpoygaZSF6heeWwIDQgaP0varUdSK1pzjeJZRjM8,9
114
+ sqlframe-3.0.0.dist-info/RECORD,,