new file: __pycache__/_type_code.cpython-313.pyc
new file: __pycache__/config.cpython-313.pyc new file: _type_code.py new file: config.py new file: connectAS.py new file: msnet/Microsoft.AnalysisServices.AdomdClient.dll new file: msnet/Microsoft.AnalysisServices.DLL new file: msnet/Microsoft.AnalysisServices.Tabular.DLL new file: test.ipynb
This commit is contained in:
commit
a926235ecc
BIN
__pycache__/_type_code.cpython-313.pyc
Normal file
BIN
__pycache__/_type_code.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/config.cpython-313.pyc
Normal file
BIN
__pycache__/config.cpython-313.pyc
Normal file
Binary file not shown.
39
_type_code.py
Normal file
39
_type_code.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
from typing import Any, cast, Callable, Dict, Iterator, List, NamedTuple, Optional, Tuple, TypeVar
|
||||||
|
from System import Decimal
|
||||||
|
from datetime import datetime
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
|
||||||
|
#Types
|
||||||
|
F = Callable[[Any], Any]
|
||||||
|
class Type_code(NamedTuple):
|
||||||
|
type_obj:F
|
||||||
|
type_name:str
|
||||||
|
|
||||||
|
def _option_type(datatype, data):
|
||||||
|
if data:
|
||||||
|
return datatype(data)
|
||||||
|
if datatype in [bool, int, float] and data == 0:
|
||||||
|
return datatype(data)
|
||||||
|
return None
|
||||||
|
|
||||||
|
adomd_type_map:Dict[str, Type_code] = {
|
||||||
|
'System.Boolean': Type_code(partial(_option_type, bool), bool.__name__),
|
||||||
|
'System.DateTime': Type_code(lambda x: datetime(x.Year, x.Month, x.Day, x.Hour, x.Minute, x.Second) if x else None, datetime.__name__),
|
||||||
|
'System.Decimal': Type_code(lambda x: Decimal.ToDouble(x) if x else None, float.__name__),
|
||||||
|
'System.Double': Type_code(partial(_option_type, float), float.__name__),
|
||||||
|
'System.Single': Type_code(partial(_option_type, float), float.__name__),
|
||||||
|
'System.String': Type_code(partial(_option_type, str), str.__name__),
|
||||||
|
'System.Guid': Type_code(partial(_option_type, str), str.__name__),
|
||||||
|
'System.UInt16': Type_code(partial(_option_type, int), int.__name__),
|
||||||
|
'System.UInt32': Type_code(partial(_option_type, int), int.__name__),
|
||||||
|
'System.UInt64': Type_code(partial(_option_type, int), int.__name__),
|
||||||
|
'System.Int16': Type_code(partial(_option_type, int), int.__name__),
|
||||||
|
'System.Int32': Type_code(partial(_option_type, int), int.__name__),
|
||||||
|
'System.Int64': Type_code(partial(_option_type, int), int.__name__),
|
||||||
|
'System.Object': Type_code(lambda x: x, 'System.Object'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def convert(datatype:str, data:Any, type_map:Dict[str, Type_code]):
|
||||||
|
type_to_convert = type_map[datatype]
|
||||||
|
return type_to_convert.type_obj(data)
|
6
config.py
Normal file
6
config.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
# 获取当前文件所在的文件夹路径
|
||||||
|
CURRENT_DIR_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
# MS.NET包的路径
|
||||||
|
NET_FOLDER = "msnet"
|
270
connectAS.py
Normal file
270
connectAS.py
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
# from pyadomd import *
|
||||||
|
|
||||||
|
|
||||||
|
import clr
|
||||||
|
import os
|
||||||
|
from System.IO import FileNotFoundException
|
||||||
|
from config import CURRENT_DIR_PATH, NET_FOLDER
|
||||||
|
|
||||||
|
# MS.NET path
|
||||||
|
AnalysisServices_path = os.path.join(
|
||||||
|
CURRENT_DIR_PATH, NET_FOLDER, "Microsoft.AnalysisServices"
|
||||||
|
)
|
||||||
|
AdomdClient_path = os.path.join(
|
||||||
|
CURRENT_DIR_PATH, NET_FOLDER, "Microsoft.AnalysisServices.AdomdClient"
|
||||||
|
)
|
||||||
|
Tabular_path = os.path.join(
|
||||||
|
CURRENT_DIR_PATH, NET_FOLDER, "Microsoft.AnalysisServices.Tabular"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add reference
|
||||||
|
try:
|
||||||
|
clr.AddReference(AdomdClient_path)
|
||||||
|
clr.AddReference(Tabular_path)
|
||||||
|
from Microsoft.AnalysisServices.AdomdClient import AdomdConnection, AdomdCommand
|
||||||
|
from Microsoft.AnalysisServices.Tabular import (
|
||||||
|
Database,
|
||||||
|
Server,
|
||||||
|
Table,
|
||||||
|
Column,
|
||||||
|
Measure,
|
||||||
|
Partition,
|
||||||
|
Level,
|
||||||
|
Hierarchy,
|
||||||
|
Trace
|
||||||
|
)
|
||||||
|
except FileNotFoundException as e:
|
||||||
|
print(
|
||||||
|
"========================================================================================"
|
||||||
|
)
|
||||||
|
print(e.ToString())
|
||||||
|
print(
|
||||||
|
"========================================================================================"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
from _type_code import adomd_type_map, convert, TypeVar, NamedTuple
|
||||||
|
|
||||||
|
# Types
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
|
class Description(NamedTuple):
|
||||||
|
"""
|
||||||
|
:param [name]: Column name
|
||||||
|
:param [type_code]: The column data type
|
||||||
|
"""
|
||||||
|
|
||||||
|
name: str
|
||||||
|
type_code: str
|
||||||
|
|
||||||
|
|
||||||
|
class Cursor:
|
||||||
|
|
||||||
|
def __init__(self, connection: AdomdConnection):
|
||||||
|
self._conn = connection
|
||||||
|
self._description: List[Description] = []
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
"""
|
||||||
|
Closes the cursor
|
||||||
|
"""
|
||||||
|
if self.is_closed:
|
||||||
|
return
|
||||||
|
self._reader.Close()
|
||||||
|
|
||||||
|
def execute(self, query: str) -> Cursor:
|
||||||
|
"""
|
||||||
|
Executes a query against the data source
|
||||||
|
|
||||||
|
:params [query]: The query to be executed
|
||||||
|
"""
|
||||||
|
self._cmd = AdomdCommand(query, self._conn)
|
||||||
|
self._reader = self._cmd.ExecuteReader()
|
||||||
|
self._field_count = self._reader.FieldCount
|
||||||
|
|
||||||
|
for i in range(self._field_count):
|
||||||
|
self._description.append(
|
||||||
|
Description(
|
||||||
|
self._reader.GetName(i),
|
||||||
|
adomd_type_map[self._reader.GetFieldType(i).ToString()].type_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def fetchone(self) -> Iterator[Tuple[T, ...]]:
|
||||||
|
"""
|
||||||
|
Fetches the current line from the last executed query
|
||||||
|
"""
|
||||||
|
while self._reader.Read():
|
||||||
|
yield tuple(
|
||||||
|
convert(
|
||||||
|
self._reader.GetFieldType(i).ToString(),
|
||||||
|
self._reader[i],
|
||||||
|
adomd_type_map,
|
||||||
|
)
|
||||||
|
for i in range(self._field_count)
|
||||||
|
)
|
||||||
|
|
||||||
|
def fetchmany(self, size=1) -> List[Tuple[T, ...]]:
|
||||||
|
"""
|
||||||
|
Fetches one or more lines from the last executed query
|
||||||
|
|
||||||
|
:params [size]: The number of rows to fetch.
|
||||||
|
If the size parameter exceeds the number of rows returned from the last executed query then fetchmany will return all rows from that query.
|
||||||
|
"""
|
||||||
|
l: List[Tuple[T, ...]] = []
|
||||||
|
try:
|
||||||
|
for i in range(size):
|
||||||
|
l.append(next(self.fetchone()))
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
return l
|
||||||
|
|
||||||
|
def fetchall(self) -> List[Tuple[T, ...]]:
|
||||||
|
"""
|
||||||
|
Fetches all the rows from the last executed query
|
||||||
|
"""
|
||||||
|
# mypy issues with list comprehension :-(
|
||||||
|
return [i for i in self.fetchone()] # type: ignore
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_closed(self) -> bool:
|
||||||
|
try:
|
||||||
|
state = self._reader.IsClosed
|
||||||
|
except AttributeError:
|
||||||
|
return True
|
||||||
|
return state
|
||||||
|
|
||||||
|
@property
|
||||||
|
def description(self) -> List[Description]:
|
||||||
|
return self._description
|
||||||
|
|
||||||
|
def __enter__(self) -> Cursor:
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback) -> None:
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
class Pyadomd:
|
||||||
|
|
||||||
|
def __init__(self, conn_str:str):
|
||||||
|
self.conn = AdomdConnection()
|
||||||
|
self.conn.ConnectionString = conn_str
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
"""
|
||||||
|
Closes the connection
|
||||||
|
"""
|
||||||
|
self.conn.Close()
|
||||||
|
|
||||||
|
def open(self) -> None:
|
||||||
|
"""
|
||||||
|
Opens the connection
|
||||||
|
"""
|
||||||
|
self.conn.Open()
|
||||||
|
|
||||||
|
def cursor(self) -> Cursor:
|
||||||
|
"""
|
||||||
|
Creates a cursor object
|
||||||
|
"""
|
||||||
|
c = Cursor(self.conn)
|
||||||
|
return c
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state(self) -> int:
|
||||||
|
"""
|
||||||
|
1 = Open
|
||||||
|
0 = Closed
|
||||||
|
"""
|
||||||
|
return self.conn.State
|
||||||
|
|
||||||
|
def __enter__(self) -> Pyadomd:
|
||||||
|
self.open()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback) -> None:
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
|
||||||
|
class Pytabular:
|
||||||
|
def __init__(self, conn_str: str):
|
||||||
|
self.server = Server()
|
||||||
|
self.server.Connect(conn_str)
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
"""Closes the connection"""
|
||||||
|
if self.server is not None:
|
||||||
|
self.server.Disconnect()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def databases(self) -> List[str]:
|
||||||
|
"""Returns a list of database names in the server"""
|
||||||
|
return [db.Name for db in self.server.Databases]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state(self) -> int:
|
||||||
|
"""1 = Open, 0 = Closed"""
|
||||||
|
return 1 if self.server is not None and self.server.Connected else 0
|
||||||
|
|
||||||
|
def __enter__(self) -> Pytabular:
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback) -> None:
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
# @property
|
||||||
|
# def tables(self) -> List[Table]:
|
||||||
|
# """
|
||||||
|
# Returns a list of tables in the database
|
||||||
|
# """
|
||||||
|
# return self.db.Model.Tables
|
||||||
|
|
||||||
|
# @property
|
||||||
|
# def partitions(self) -> List[Partition]:
|
||||||
|
# """
|
||||||
|
# Returns a list of partitions in the database
|
||||||
|
# """
|
||||||
|
# return self.db.Model.Partitions
|
||||||
|
|
||||||
|
# @property
|
||||||
|
# def levels(self) -> List[Level]:
|
||||||
|
# """
|
||||||
|
# Returns a list of levels in the database
|
||||||
|
# """
|
||||||
|
# return self.db.Model.Levels
|
||||||
|
|
||||||
|
# @property
|
||||||
|
# def hierarchies(self) -> List[Hierarchy]:
|
||||||
|
# """
|
||||||
|
# Returns a list of hierarchies in the database
|
||||||
|
# """
|
||||||
|
# return self.db.Model.Hierarchies
|
||||||
|
|
||||||
|
# @property
|
||||||
|
# def measures(self) -> List[Measure]:
|
||||||
|
# """
|
||||||
|
# Returns a list of measures in the database
|
||||||
|
# """
|
||||||
|
# return self.db.Model.Measures
|
||||||
|
|
||||||
|
# @property
|
||||||
|
# def traces(self) -> List[Trace]:
|
||||||
|
# """
|
||||||
|
# Returns a list of traces in the database
|
||||||
|
# """
|
||||||
|
# return self.db.Model.Traces
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
conn_str = "Provider=MSOLAP;Data Source=localhost"
|
||||||
|
with Pytabular(conn_str) as conn:
|
||||||
|
print("Connected to Analysis Services server")
|
||||||
|
print("Available databases:")
|
||||||
|
for db in conn.databases:
|
||||||
|
print(f"- {db}")
|
BIN
msnet/Microsoft.AnalysisServices.AdomdClient.dll
Normal file
BIN
msnet/Microsoft.AnalysisServices.AdomdClient.dll
Normal file
Binary file not shown.
BIN
msnet/Microsoft.AnalysisServices.DLL
Normal file
BIN
msnet/Microsoft.AnalysisServices.DLL
Normal file
Binary file not shown.
BIN
msnet/Microsoft.AnalysisServices.Tabular.DLL
Normal file
BIN
msnet/Microsoft.AnalysisServices.Tabular.DLL
Normal file
Binary file not shown.
0
test.ipynb
Normal file
0
test.ipynb
Normal file
Loading…
Reference in New Issue
Block a user